Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    3)  * Common code for Intel Running Average Power Limit (RAPL) support.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4)  * Copyright (c) 2019, Intel Corporation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14) #include <linux/log2.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15) #include <linux/bitmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17) #include <linux/sysfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18) #include <linux/cpu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19) #include <linux/powercap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20) #include <linux/suspend.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21) #include <linux/intel_rapl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22) #include <linux/processor.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25) #include <asm/iosf_mbi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26) #include <asm/cpu_device_id.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27) #include <asm/intel-family.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29) /* bitmasks for RAPL MSRs, used by primitive access functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30) #define ENERGY_STATUS_MASK      0xffffffff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32) #define POWER_LIMIT1_MASK       0x7FFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33) #define POWER_LIMIT1_ENABLE     BIT(15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34) #define POWER_LIMIT1_CLAMP      BIT(16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36) #define POWER_LIMIT2_MASK       (0x7FFFULL<<32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37) #define POWER_LIMIT2_ENABLE     BIT_ULL(47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38) #define POWER_LIMIT2_CLAMP      BIT_ULL(48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39) #define POWER_HIGH_LOCK         BIT_ULL(63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40) #define POWER_LOW_LOCK          BIT(31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42) #define POWER_LIMIT4_MASK		0x1FFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44) #define TIME_WINDOW1_MASK       (0x7FULL<<17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45) #define TIME_WINDOW2_MASK       (0x7FULL<<49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47) #define POWER_UNIT_OFFSET	0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48) #define POWER_UNIT_MASK		0x0F
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50) #define ENERGY_UNIT_OFFSET	0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51) #define ENERGY_UNIT_MASK	0x1F00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53) #define TIME_UNIT_OFFSET	0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54) #define TIME_UNIT_MASK		0xF0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56) #define POWER_INFO_MAX_MASK     (0x7fffULL<<32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57) #define POWER_INFO_MIN_MASK     (0x7fffULL<<16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58) #define POWER_INFO_MAX_TIME_WIN_MASK     (0x3fULL<<48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59) #define POWER_INFO_THERMAL_SPEC_MASK     0x7fff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61) #define PERF_STATUS_THROTTLE_TIME_MASK 0xffffffff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62) #define PP_POLICY_MASK         0x1F
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64) /* Non HW constants */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65) #define RAPL_PRIMITIVE_DERIVED       BIT(1)	/* not from raw data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66) #define RAPL_PRIMITIVE_DUMMY         BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68) #define TIME_WINDOW_MAX_MSEC 40000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69) #define TIME_WINDOW_MIN_MSEC 250
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70) #define ENERGY_UNIT_SCALE    1000	/* scale from driver unit to powercap unit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71) enum unit_type {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72) 	ARBITRARY_UNIT,		/* no translation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73) 	POWER_UNIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) 	ENERGY_UNIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) 	TIME_UNIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78) /* per domain data, some are optional */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79) #define NR_RAW_PRIMITIVES (NR_RAPL_PRIMITIVES - 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81) #define	DOMAIN_STATE_INACTIVE           BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82) #define	DOMAIN_STATE_POWER_LIMIT_SET    BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83) #define DOMAIN_STATE_BIOS_LOCKED        BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85) static const char pl1_name[] = "long_term";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86) static const char pl2_name[] = "short_term";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87) static const char pl4_name[] = "peak_power";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89) #define power_zone_to_rapl_domain(_zone) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90) 	container_of(_zone, struct rapl_domain, power_zone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92) struct rapl_defaults {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93) 	u8 floor_freq_reg_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94) 	int (*check_unit)(struct rapl_package *rp, int cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95) 	void (*set_floor_freq)(struct rapl_domain *rd, bool mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96) 	u64 (*compute_time_window)(struct rapl_package *rp, u64 val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97) 				    bool to_raw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98) 	unsigned int dram_domain_energy_unit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99) 	unsigned int psys_domain_energy_unit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101) static struct rapl_defaults *rapl_defaults;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103) /* Sideband MBI registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104) #define IOSF_CPU_POWER_BUDGET_CTL_BYT (0x2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105) #define IOSF_CPU_POWER_BUDGET_CTL_TNG (0xdf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107) #define PACKAGE_PLN_INT_SAVED   BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108) #define MAX_PRIM_NAME (32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110) /* per domain data. used to describe individual knobs such that access function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111)  * can be consolidated into one instead of many inline functions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113) struct rapl_primitive_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114) 	const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115) 	u64 mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116) 	int shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117) 	enum rapl_domain_reg_id id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118) 	enum unit_type unit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119) 	u32 flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122) #define PRIMITIVE_INFO_INIT(p, m, s, i, u, f) {	\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123) 		.name = #p,			\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124) 		.mask = m,			\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125) 		.shift = s,			\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126) 		.id = i,			\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127) 		.unit = u,			\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128) 		.flag = f			\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131) static void rapl_init_domains(struct rapl_package *rp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132) static int rapl_read_data_raw(struct rapl_domain *rd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133) 			      enum rapl_primitives prim,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134) 			      bool xlate, u64 *data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135) static int rapl_write_data_raw(struct rapl_domain *rd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136) 			       enum rapl_primitives prim,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137) 			       unsigned long long value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138) static u64 rapl_unit_xlate(struct rapl_domain *rd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139) 			   enum unit_type type, u64 value, int to_raw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140) static void package_power_limit_irq_save(struct rapl_package *rp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142) static LIST_HEAD(rapl_packages);	/* guarded by CPU hotplug lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144) static const char *const rapl_domain_names[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145) 	"package",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146) 	"core",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147) 	"uncore",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148) 	"dram",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149) 	"psys",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152) static int get_energy_counter(struct powercap_zone *power_zone,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153) 			      u64 *energy_raw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155) 	struct rapl_domain *rd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156) 	u64 energy_now;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158) 	/* prevent CPU hotplug, make sure the RAPL domain does not go
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159) 	 * away while reading the counter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161) 	get_online_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162) 	rd = power_zone_to_rapl_domain(power_zone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164) 	if (!rapl_read_data_raw(rd, ENERGY_COUNTER, true, &energy_now)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165) 		*energy_raw = energy_now;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166) 		put_online_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170) 	put_online_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172) 	return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175) static int get_max_energy_counter(struct powercap_zone *pcd_dev, u64 *energy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177) 	struct rapl_domain *rd = power_zone_to_rapl_domain(pcd_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179) 	*energy = rapl_unit_xlate(rd, ENERGY_UNIT, ENERGY_STATUS_MASK, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183) static int release_zone(struct powercap_zone *power_zone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185) 	struct rapl_domain *rd = power_zone_to_rapl_domain(power_zone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186) 	struct rapl_package *rp = rd->rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188) 	/* package zone is the last zone of a package, we can free
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189) 	 * memory here since all children has been unregistered.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191) 	if (rd->id == RAPL_DOMAIN_PACKAGE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192) 		kfree(rd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193) 		rp->domains = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200) static int find_nr_power_limit(struct rapl_domain *rd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202) 	int i, nr_pl = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204) 	for (i = 0; i < NR_POWER_LIMITS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205) 		if (rd->rpl[i].name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206) 			nr_pl++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) 	return nr_pl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212) static int set_domain_enable(struct powercap_zone *power_zone, bool mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214) 	struct rapl_domain *rd = power_zone_to_rapl_domain(power_zone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216) 	if (rd->state & DOMAIN_STATE_BIOS_LOCKED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217) 		return -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219) 	get_online_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220) 	rapl_write_data_raw(rd, PL1_ENABLE, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221) 	if (rapl_defaults->set_floor_freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222) 		rapl_defaults->set_floor_freq(rd, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223) 	put_online_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228) static int get_domain_enable(struct powercap_zone *power_zone, bool *mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230) 	struct rapl_domain *rd = power_zone_to_rapl_domain(power_zone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231) 	u64 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233) 	if (rd->state & DOMAIN_STATE_BIOS_LOCKED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234) 		*mode = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237) 	get_online_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238) 	if (rapl_read_data_raw(rd, PL1_ENABLE, true, &val)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239) 		put_online_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242) 	*mode = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243) 	put_online_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248) /* per RAPL domain ops, in the order of rapl_domain_type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249) static const struct powercap_zone_ops zone_ops[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250) 	/* RAPL_DOMAIN_PACKAGE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252) 	 .get_energy_uj = get_energy_counter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253) 	 .get_max_energy_range_uj = get_max_energy_counter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254) 	 .release = release_zone,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255) 	 .set_enable = set_domain_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256) 	 .get_enable = get_domain_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257) 	 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258) 	/* RAPL_DOMAIN_PP0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260) 	 .get_energy_uj = get_energy_counter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261) 	 .get_max_energy_range_uj = get_max_energy_counter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262) 	 .release = release_zone,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) 	 .set_enable = set_domain_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264) 	 .get_enable = get_domain_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265) 	 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266) 	/* RAPL_DOMAIN_PP1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268) 	 .get_energy_uj = get_energy_counter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269) 	 .get_max_energy_range_uj = get_max_energy_counter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270) 	 .release = release_zone,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271) 	 .set_enable = set_domain_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272) 	 .get_enable = get_domain_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273) 	 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274) 	/* RAPL_DOMAIN_DRAM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276) 	 .get_energy_uj = get_energy_counter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277) 	 .get_max_energy_range_uj = get_max_energy_counter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278) 	 .release = release_zone,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279) 	 .set_enable = set_domain_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280) 	 .get_enable = get_domain_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281) 	 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282) 	/* RAPL_DOMAIN_PLATFORM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284) 	 .get_energy_uj = get_energy_counter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285) 	 .get_max_energy_range_uj = get_max_energy_counter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) 	 .release = release_zone,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) 	 .set_enable = set_domain_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) 	 .get_enable = get_domain_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) 	 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293)  * Constraint index used by powercap can be different than power limit (PL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294)  * index in that some  PLs maybe missing due to non-existent MSRs. So we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295)  * need to convert here by finding the valid PLs only (name populated).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297) static int contraint_to_pl(struct rapl_domain *rd, int cid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299) 	int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301) 	for (i = 0, j = 0; i < NR_POWER_LIMITS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302) 		if ((rd->rpl[i].name) && j++ == cid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303) 			pr_debug("%s: index %d\n", __func__, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304) 			return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307) 	pr_err("Cannot find matching power limit for constraint %d\n", cid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309) 	return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312) static int set_power_limit(struct powercap_zone *power_zone, int cid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313) 			   u64 power_limit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315) 	struct rapl_domain *rd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316) 	struct rapl_package *rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318) 	int id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320) 	get_online_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321) 	rd = power_zone_to_rapl_domain(power_zone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322) 	id = contraint_to_pl(rd, cid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323) 	if (id < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324) 		ret = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325) 		goto set_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328) 	rp = rd->rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330) 	if (rd->state & DOMAIN_STATE_BIOS_LOCKED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331) 		dev_warn(&power_zone->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332) 			 "%s locked by BIOS, monitoring only\n", rd->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333) 		ret = -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334) 		goto set_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337) 	switch (rd->rpl[id].prim_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338) 	case PL1_ENABLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339) 		rapl_write_data_raw(rd, POWER_LIMIT1, power_limit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341) 	case PL2_ENABLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342) 		rapl_write_data_raw(rd, POWER_LIMIT2, power_limit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344) 	case PL4_ENABLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345) 		rapl_write_data_raw(rd, POWER_LIMIT4, power_limit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348) 		ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350) 	if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351) 		package_power_limit_irq_save(rp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352) set_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353) 	put_online_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357) static int get_current_power_limit(struct powercap_zone *power_zone, int cid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358) 				   u64 *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) 	struct rapl_domain *rd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) 	u64 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362) 	int prim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364) 	int id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366) 	get_online_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367) 	rd = power_zone_to_rapl_domain(power_zone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) 	id = contraint_to_pl(rd, cid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) 	if (id < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370) 		ret = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371) 		goto get_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374) 	switch (rd->rpl[id].prim_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375) 	case PL1_ENABLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376) 		prim = POWER_LIMIT1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378) 	case PL2_ENABLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379) 		prim = POWER_LIMIT2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381) 	case PL4_ENABLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382) 		prim = POWER_LIMIT4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385) 		put_online_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388) 	if (rapl_read_data_raw(rd, prim, true, &val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389) 		ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391) 		*data = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393) get_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394) 	put_online_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399) static int set_time_window(struct powercap_zone *power_zone, int cid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400) 			   u64 window)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402) 	struct rapl_domain *rd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404) 	int id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406) 	get_online_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407) 	rd = power_zone_to_rapl_domain(power_zone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408) 	id = contraint_to_pl(rd, cid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409) 	if (id < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410) 		ret = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411) 		goto set_time_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) 	switch (rd->rpl[id].prim_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415) 	case PL1_ENABLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416) 		rapl_write_data_raw(rd, TIME_WINDOW1, window);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418) 	case PL2_ENABLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419) 		rapl_write_data_raw(rd, TIME_WINDOW2, window);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422) 		ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) set_time_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426) 	put_online_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430) static int get_time_window(struct powercap_zone *power_zone, int cid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431) 			   u64 *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433) 	struct rapl_domain *rd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434) 	u64 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436) 	int id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) 	get_online_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439) 	rd = power_zone_to_rapl_domain(power_zone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) 	id = contraint_to_pl(rd, cid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) 	if (id < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) 		ret = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) 		goto get_time_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) 	switch (rd->rpl[id].prim_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) 	case PL1_ENABLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) 		ret = rapl_read_data_raw(rd, TIME_WINDOW1, true, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450) 	case PL2_ENABLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451) 		ret = rapl_read_data_raw(rd, TIME_WINDOW2, true, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453) 	case PL4_ENABLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) 		 * Time window parameter is not applicable for PL4 entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456) 		 * so assigining '0' as default value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458) 		val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461) 		put_online_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) 	if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) 		*data = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) get_time_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) 	put_online_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473) static const char *get_constraint_name(struct powercap_zone *power_zone,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474) 				       int cid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476) 	struct rapl_domain *rd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477) 	int id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) 	rd = power_zone_to_rapl_domain(power_zone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) 	id = contraint_to_pl(rd, cid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) 	if (id >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) 		return rd->rpl[id].name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487) static int get_max_power(struct powercap_zone *power_zone, int id, u64 *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489) 	struct rapl_domain *rd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490) 	u64 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491) 	int prim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494) 	get_online_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495) 	rd = power_zone_to_rapl_domain(power_zone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496) 	switch (rd->rpl[id].prim_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497) 	case PL1_ENABLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498) 		prim = THERMAL_SPEC_POWER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500) 	case PL2_ENABLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501) 		prim = MAX_POWER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503) 	case PL4_ENABLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504) 		prim = MAX_POWER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507) 		put_online_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510) 	if (rapl_read_data_raw(rd, prim, true, &val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511) 		ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513) 		*data = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515) 	/* As a generalization rule, PL4 would be around two times PL2. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516) 	if (rd->rpl[id].prim_id == PL4_ENABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517) 		*data = *data * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519) 	put_online_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524) static const struct powercap_zone_constraint_ops constraint_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525) 	.set_power_limit_uw = set_power_limit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526) 	.get_power_limit_uw = get_current_power_limit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527) 	.set_time_window_us = set_time_window,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528) 	.get_time_window_us = get_time_window,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529) 	.get_max_power_uw = get_max_power,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530) 	.get_name = get_constraint_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533) /* called after domain detection and package level data are set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534) static void rapl_init_domains(struct rapl_package *rp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536) 	enum rapl_domain_type i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537) 	enum rapl_domain_reg_id j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) 	struct rapl_domain *rd = rp->domains;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) 	for (i = 0; i < RAPL_DOMAIN_MAX; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) 		unsigned int mask = rp->domain_map & (1 << i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543) 		if (!mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546) 		rd->rp = rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548) 		if (i == RAPL_DOMAIN_PLATFORM && rp->id > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549) 			snprintf(rd->name, RAPL_DOMAIN_NAME_LENGTH, "psys-%d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550) 				cpu_data(rp->lead_cpu).phys_proc_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551) 		} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552) 			snprintf(rd->name, RAPL_DOMAIN_NAME_LENGTH, "%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553) 				rapl_domain_names[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555) 		rd->id = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556) 		rd->rpl[0].prim_id = PL1_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557) 		rd->rpl[0].name = pl1_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560) 		 * The PL2 power domain is applicable for limits two
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561) 		 * and limits three
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563) 		if (rp->priv->limits[i] >= 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564) 			rd->rpl[1].prim_id = PL2_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565) 			rd->rpl[1].name = pl2_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568) 		/* Enable PL4 domain if the total power limits are three */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569) 		if (rp->priv->limits[i] == 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) 			rd->rpl[2].prim_id = PL4_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) 			rd->rpl[2].name = pl4_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574) 		for (j = 0; j < RAPL_DOMAIN_REG_MAX; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575) 			rd->regs[j] = rp->priv->regs[i][j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577) 		switch (i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578) 		case RAPL_DOMAIN_DRAM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579) 			rd->domain_energy_unit =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580) 			    rapl_defaults->dram_domain_energy_unit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581) 			if (rd->domain_energy_unit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) 				pr_info("DRAM domain energy unit %dpj\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) 					rd->domain_energy_unit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) 		case RAPL_DOMAIN_PLATFORM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) 			rd->domain_energy_unit =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587) 			    rapl_defaults->psys_domain_energy_unit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588) 			if (rd->domain_energy_unit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589) 				pr_info("Platform domain energy unit %dpj\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590) 					rd->domain_energy_unit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595) 		rd++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599) static u64 rapl_unit_xlate(struct rapl_domain *rd, enum unit_type type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600) 			   u64 value, int to_raw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602) 	u64 units = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603) 	struct rapl_package *rp = rd->rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604) 	u64 scale = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606) 	switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607) 	case POWER_UNIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608) 		units = rp->power_unit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610) 	case ENERGY_UNIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611) 		scale = ENERGY_UNIT_SCALE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612) 		/* per domain unit takes precedence */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613) 		if (rd->domain_energy_unit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614) 			units = rd->domain_energy_unit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616) 			units = rp->energy_unit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) 	case TIME_UNIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619) 		return rapl_defaults->compute_time_window(rp, value, to_raw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620) 	case ARBITRARY_UNIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622) 		return value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625) 	if (to_raw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626) 		return div64_u64(value, units) * scale;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628) 	value *= units;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630) 	return div64_u64(value, scale);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633) /* in the order of enum rapl_primitives */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634) static struct rapl_primitive_info rpi[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635) 	/* name, mask, shift, msr index, unit divisor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636) 	PRIMITIVE_INFO_INIT(ENERGY_COUNTER, ENERGY_STATUS_MASK, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637) 			    RAPL_DOMAIN_REG_STATUS, ENERGY_UNIT, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638) 	PRIMITIVE_INFO_INIT(POWER_LIMIT1, POWER_LIMIT1_MASK, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639) 			    RAPL_DOMAIN_REG_LIMIT, POWER_UNIT, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640) 	PRIMITIVE_INFO_INIT(POWER_LIMIT2, POWER_LIMIT2_MASK, 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641) 			    RAPL_DOMAIN_REG_LIMIT, POWER_UNIT, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642) 	PRIMITIVE_INFO_INIT(POWER_LIMIT4, POWER_LIMIT4_MASK, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643) 				RAPL_DOMAIN_REG_PL4, POWER_UNIT, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644) 	PRIMITIVE_INFO_INIT(FW_LOCK, POWER_LOW_LOCK, 31,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645) 			    RAPL_DOMAIN_REG_LIMIT, ARBITRARY_UNIT, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646) 	PRIMITIVE_INFO_INIT(PL1_ENABLE, POWER_LIMIT1_ENABLE, 15,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) 			    RAPL_DOMAIN_REG_LIMIT, ARBITRARY_UNIT, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648) 	PRIMITIVE_INFO_INIT(PL1_CLAMP, POWER_LIMIT1_CLAMP, 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) 			    RAPL_DOMAIN_REG_LIMIT, ARBITRARY_UNIT, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) 	PRIMITIVE_INFO_INIT(PL2_ENABLE, POWER_LIMIT2_ENABLE, 47,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) 			    RAPL_DOMAIN_REG_LIMIT, ARBITRARY_UNIT, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652) 	PRIMITIVE_INFO_INIT(PL2_CLAMP, POWER_LIMIT2_CLAMP, 48,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653) 			    RAPL_DOMAIN_REG_LIMIT, ARBITRARY_UNIT, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) 	PRIMITIVE_INFO_INIT(PL4_ENABLE, POWER_LIMIT4_MASK, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655) 				RAPL_DOMAIN_REG_PL4, ARBITRARY_UNIT, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) 	PRIMITIVE_INFO_INIT(TIME_WINDOW1, TIME_WINDOW1_MASK, 17,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657) 			    RAPL_DOMAIN_REG_LIMIT, TIME_UNIT, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658) 	PRIMITIVE_INFO_INIT(TIME_WINDOW2, TIME_WINDOW2_MASK, 49,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659) 			    RAPL_DOMAIN_REG_LIMIT, TIME_UNIT, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660) 	PRIMITIVE_INFO_INIT(THERMAL_SPEC_POWER, POWER_INFO_THERMAL_SPEC_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661) 			    0, RAPL_DOMAIN_REG_INFO, POWER_UNIT, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662) 	PRIMITIVE_INFO_INIT(MAX_POWER, POWER_INFO_MAX_MASK, 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) 			    RAPL_DOMAIN_REG_INFO, POWER_UNIT, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664) 	PRIMITIVE_INFO_INIT(MIN_POWER, POWER_INFO_MIN_MASK, 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665) 			    RAPL_DOMAIN_REG_INFO, POWER_UNIT, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) 	PRIMITIVE_INFO_INIT(MAX_TIME_WINDOW, POWER_INFO_MAX_TIME_WIN_MASK, 48,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) 			    RAPL_DOMAIN_REG_INFO, TIME_UNIT, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) 	PRIMITIVE_INFO_INIT(THROTTLED_TIME, PERF_STATUS_THROTTLE_TIME_MASK, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) 			    RAPL_DOMAIN_REG_PERF, TIME_UNIT, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) 	PRIMITIVE_INFO_INIT(PRIORITY_LEVEL, PP_POLICY_MASK, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671) 			    RAPL_DOMAIN_REG_POLICY, ARBITRARY_UNIT, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672) 	/* non-hardware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) 	PRIMITIVE_INFO_INIT(AVERAGE_POWER, 0, 0, 0, POWER_UNIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674) 			    RAPL_PRIMITIVE_DERIVED),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675) 	{NULL, 0, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678) /* Read primitive data based on its related struct rapl_primitive_info.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679)  * if xlate flag is set, return translated data based on data units, i.e.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680)  * time, energy, and power.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681)  * RAPL MSRs are non-architectual and are laid out not consistently across
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682)  * domains. Here we use primitive info to allow writing consolidated access
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683)  * functions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684)  * For a given primitive, it is processed by MSR mask and shift. Unit conversion
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685)  * is pre-assigned based on RAPL unit MSRs read at init time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686)  * 63-------------------------- 31--------------------------- 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687)  * |                           xxxxx (mask)                   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688)  * |                                |<- shift ----------------|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689)  * 63-------------------------- 31--------------------------- 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691) static int rapl_read_data_raw(struct rapl_domain *rd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692) 			      enum rapl_primitives prim, bool xlate, u64 *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694) 	u64 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695) 	struct rapl_primitive_info *rp = &rpi[prim];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) 	struct reg_action ra;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697) 	int cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) 	if (!rp->name || rp->flag & RAPL_PRIMITIVE_DUMMY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702) 	ra.reg = rd->regs[rp->id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703) 	if (!ra.reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) 	cpu = rd->rp->lead_cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) 	/* domain with 2 limits has different bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) 	if (prim == FW_LOCK && rd->rp->priv->limits[rd->id] == 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710) 		rp->mask = POWER_HIGH_LOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711) 		rp->shift = 63;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713) 	/* non-hardware data are collected by the polling thread */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) 	if (rp->flag & RAPL_PRIMITIVE_DERIVED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715) 		*data = rd->rdd.primitives[prim];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719) 	ra.mask = rp->mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721) 	if (rd->rp->priv->read_raw(cpu, &ra)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722) 		pr_debug("failed to read reg 0x%llx on cpu %d\n", ra.reg, cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) 	value = ra.value >> rp->shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) 	if (xlate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729) 		*data = rapl_unit_xlate(rd, rp->unit, value, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731) 		*data = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736) /* Similar use of primitive info in the read counterpart */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737) static int rapl_write_data_raw(struct rapl_domain *rd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738) 			       enum rapl_primitives prim,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739) 			       unsigned long long value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) 	struct rapl_primitive_info *rp = &rpi[prim];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) 	int cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) 	u64 bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744) 	struct reg_action ra;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747) 	cpu = rd->rp->lead_cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748) 	bits = rapl_unit_xlate(rd, rp->unit, value, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749) 	bits <<= rp->shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750) 	bits &= rp->mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752) 	memset(&ra, 0, sizeof(ra));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754) 	ra.reg = rd->regs[rp->id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755) 	ra.mask = rp->mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) 	ra.value = bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) 	ret = rd->rp->priv->write_raw(cpu, &ra);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764)  * Raw RAPL data stored in MSRs are in certain scales. We need to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765)  * convert them into standard units based on the units reported in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766)  * the RAPL unit MSRs. This is specific to CPUs as the method to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767)  * calculate units differ on different CPUs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768)  * We convert the units to below format based on CPUs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769)  * i.e.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770)  * energy unit: picoJoules  : Represented in picoJoules by default
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771)  * power unit : microWatts  : Represented in milliWatts by default
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772)  * time unit  : microseconds: Represented in seconds by default
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774) static int rapl_check_unit_core(struct rapl_package *rp, int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776) 	struct reg_action ra;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777) 	u32 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779) 	ra.reg = rp->priv->reg_unit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780) 	ra.mask = ~0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) 	if (rp->priv->read_raw(cpu, &ra)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) 		pr_err("Failed to read power unit REG 0x%llx on CPU %d, exit.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) 		       rp->priv->reg_unit, cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) 	value = (ra.value & ENERGY_UNIT_MASK) >> ENERGY_UNIT_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) 	rp->energy_unit = ENERGY_UNIT_SCALE * 1000000 / (1 << value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) 	value = (ra.value & POWER_UNIT_MASK) >> POWER_UNIT_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791) 	rp->power_unit = 1000000 / (1 << value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) 	value = (ra.value & TIME_UNIT_MASK) >> TIME_UNIT_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) 	rp->time_unit = 1000000 / (1 << value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796) 	pr_debug("Core CPU %s energy=%dpJ, time=%dus, power=%duW\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) 		 rp->name, rp->energy_unit, rp->time_unit, rp->power_unit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802) static int rapl_check_unit_atom(struct rapl_package *rp, int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804) 	struct reg_action ra;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805) 	u32 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807) 	ra.reg = rp->priv->reg_unit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808) 	ra.mask = ~0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) 	if (rp->priv->read_raw(cpu, &ra)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810) 		pr_err("Failed to read power unit REG 0x%llx on CPU %d, exit.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811) 		       rp->priv->reg_unit, cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815) 	value = (ra.value & ENERGY_UNIT_MASK) >> ENERGY_UNIT_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816) 	rp->energy_unit = ENERGY_UNIT_SCALE * 1 << value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818) 	value = (ra.value & POWER_UNIT_MASK) >> POWER_UNIT_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819) 	rp->power_unit = (1 << value) * 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821) 	value = (ra.value & TIME_UNIT_MASK) >> TIME_UNIT_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822) 	rp->time_unit = 1000000 / (1 << value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824) 	pr_debug("Atom %s energy=%dpJ, time=%dus, power=%duW\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825) 		 rp->name, rp->energy_unit, rp->time_unit, rp->power_unit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830) static void power_limit_irq_save_cpu(void *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832) 	u32 l, h = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833) 	struct rapl_package *rp = (struct rapl_package *)info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835) 	/* save the state of PLN irq mask bit before disabling it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836) 	rdmsr_safe(MSR_IA32_PACKAGE_THERM_INTERRUPT, &l, &h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837) 	if (!(rp->power_limit_irq & PACKAGE_PLN_INT_SAVED)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838) 		rp->power_limit_irq = l & PACKAGE_THERM_INT_PLN_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839) 		rp->power_limit_irq |= PACKAGE_PLN_INT_SAVED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) 	l &= ~PACKAGE_THERM_INT_PLN_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842) 	wrmsr_safe(MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845) /* REVISIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846)  * When package power limit is set artificially low by RAPL, LVT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847)  * thermal interrupt for package power limit should be ignored
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848)  * since we are not really exceeding the real limit. The intention
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849)  * is to avoid excessive interrupts while we are trying to save power.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850)  * A useful feature might be routing the package_power_limit interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851)  * to userspace via eventfd. once we have a usecase, this is simple
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852)  * to do by adding an atomic notifier.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855) static void package_power_limit_irq_save(struct rapl_package *rp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) 	if (!boot_cpu_has(X86_FEATURE_PTS) || !boot_cpu_has(X86_FEATURE_PLN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860) 	smp_call_function_single(rp->lead_cpu, power_limit_irq_save_cpu, rp, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864)  * Restore per package power limit interrupt enable state. Called from cpu
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865)  * hotplug code on package removal.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867) static void package_power_limit_irq_restore(struct rapl_package *rp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869) 	u32 l, h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871) 	if (!boot_cpu_has(X86_FEATURE_PTS) || !boot_cpu_has(X86_FEATURE_PLN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874) 	/* irq enable state not saved, nothing to restore */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875) 	if (!(rp->power_limit_irq & PACKAGE_PLN_INT_SAVED))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) 	rdmsr_safe(MSR_IA32_PACKAGE_THERM_INTERRUPT, &l, &h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) 	if (rp->power_limit_irq & PACKAGE_THERM_INT_PLN_ENABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) 		l |= PACKAGE_THERM_INT_PLN_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) 		l &= ~PACKAGE_THERM_INT_PLN_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) 	wrmsr_safe(MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888) static void set_floor_freq_default(struct rapl_domain *rd, bool mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890) 	int nr_powerlimit = find_nr_power_limit(rd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892) 	/* always enable clamp such that p-state can go below OS requested
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893) 	 * range. power capping priority over guranteed frequency.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895) 	rapl_write_data_raw(rd, PL1_CLAMP, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897) 	/* some domains have pl2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898) 	if (nr_powerlimit > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899) 		rapl_write_data_raw(rd, PL2_ENABLE, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900) 		rapl_write_data_raw(rd, PL2_CLAMP, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904) static void set_floor_freq_atom(struct rapl_domain *rd, bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906) 	static u32 power_ctrl_orig_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) 	u32 mdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) 	if (!rapl_defaults->floor_freq_reg_addr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) 		pr_err("Invalid floor frequency config register\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) 	if (!power_ctrl_orig_val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) 		iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_CR_READ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) 			      rapl_defaults->floor_freq_reg_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917) 			      &power_ctrl_orig_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918) 	mdata = power_ctrl_orig_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919) 	if (enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920) 		mdata &= ~(0x7f << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921) 		mdata |= 1 << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923) 	iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_CR_WRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924) 		       rapl_defaults->floor_freq_reg_addr, mdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927) static u64 rapl_compute_time_window_core(struct rapl_package *rp, u64 value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928) 					 bool to_raw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) 	u64 f, y;		/* fraction and exp. used for time unit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933) 	 * Special processing based on 2^Y*(1+F/4), refer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934) 	 * to Intel Software Developer's manual Vol.3B: CH 14.9.3.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936) 	if (!to_raw) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937) 		f = (value & 0x60) >> 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938) 		y = value & 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) 		value = (1 << y) * (4 + f) * rp->time_unit / 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941) 		do_div(value, rp->time_unit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942) 		y = ilog2(value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943) 		f = div64_u64(4 * (value - (1 << y)), 1 << y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944) 		value = (y & 0x1f) | ((f & 0x3) << 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) 	return value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) static u64 rapl_compute_time_window_atom(struct rapl_package *rp, u64 value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) 					 bool to_raw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) 	 * Atom time unit encoding is straight forward val * time_unit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) 	 * where time_unit is default to 1 sec. Never 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956) 	if (!to_raw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957) 		return (value) ? value *= rp->time_unit : rp->time_unit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959) 	value = div64_u64(value, rp->time_unit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961) 	return value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964) static const struct rapl_defaults rapl_defaults_core = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965) 	.floor_freq_reg_addr = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) 	.check_unit = rapl_check_unit_core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) 	.set_floor_freq = set_floor_freq_default,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) 	.compute_time_window = rapl_compute_time_window_core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) static const struct rapl_defaults rapl_defaults_hsw_server = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 	.check_unit = rapl_check_unit_core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) 	.set_floor_freq = set_floor_freq_default,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) 	.compute_time_window = rapl_compute_time_window_core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) 	.dram_domain_energy_unit = 15300,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978) static const struct rapl_defaults rapl_defaults_spr_server = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) 	.check_unit = rapl_check_unit_core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980) 	.set_floor_freq = set_floor_freq_default,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981) 	.compute_time_window = rapl_compute_time_window_core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982) 	.dram_domain_energy_unit = 15300,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983) 	.psys_domain_energy_unit = 1000000000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986) static const struct rapl_defaults rapl_defaults_byt = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987) 	.floor_freq_reg_addr = IOSF_CPU_POWER_BUDGET_CTL_BYT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) 	.check_unit = rapl_check_unit_atom,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) 	.set_floor_freq = set_floor_freq_atom,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) 	.compute_time_window = rapl_compute_time_window_atom,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) static const struct rapl_defaults rapl_defaults_tng = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) 	.floor_freq_reg_addr = IOSF_CPU_POWER_BUDGET_CTL_TNG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 	.check_unit = rapl_check_unit_atom,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) 	.set_floor_freq = set_floor_freq_atom,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) 	.compute_time_window = rapl_compute_time_window_atom,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) static const struct rapl_defaults rapl_defaults_ann = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) 	.floor_freq_reg_addr = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) 	.check_unit = rapl_check_unit_atom,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) 	.set_floor_freq = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) 	.compute_time_window = rapl_compute_time_window_atom,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) static const struct rapl_defaults rapl_defaults_cht = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) 	.floor_freq_reg_addr = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) 	.check_unit = rapl_check_unit_atom,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) 	.set_floor_freq = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) 	.compute_time_window = rapl_compute_time_window_atom,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) static const struct x86_cpu_id rapl_ids[] __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) 	X86_MATCH_INTEL_FAM6_MODEL(SANDYBRIDGE,		&rapl_defaults_core),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) 	X86_MATCH_INTEL_FAM6_MODEL(SANDYBRIDGE_X,	&rapl_defaults_core),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) 	X86_MATCH_INTEL_FAM6_MODEL(IVYBRIDGE,		&rapl_defaults_core),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) 	X86_MATCH_INTEL_FAM6_MODEL(IVYBRIDGE_X,		&rapl_defaults_core),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) 	X86_MATCH_INTEL_FAM6_MODEL(HASWELL,		&rapl_defaults_core),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) 	X86_MATCH_INTEL_FAM6_MODEL(HASWELL_L,		&rapl_defaults_core),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) 	X86_MATCH_INTEL_FAM6_MODEL(HASWELL_G,		&rapl_defaults_core),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) 	X86_MATCH_INTEL_FAM6_MODEL(HASWELL_X,		&rapl_defaults_hsw_server),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) 	X86_MATCH_INTEL_FAM6_MODEL(BROADWELL,		&rapl_defaults_core),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) 	X86_MATCH_INTEL_FAM6_MODEL(BROADWELL_G,		&rapl_defaults_core),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) 	X86_MATCH_INTEL_FAM6_MODEL(BROADWELL_D,		&rapl_defaults_core),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) 	X86_MATCH_INTEL_FAM6_MODEL(BROADWELL_X,		&rapl_defaults_hsw_server),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) 	X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE,		&rapl_defaults_core),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) 	X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE_L,		&rapl_defaults_core),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) 	X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE_X,		&rapl_defaults_hsw_server),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) 	X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE_L,		&rapl_defaults_core),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) 	X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE,		&rapl_defaults_core),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) 	X86_MATCH_INTEL_FAM6_MODEL(CANNONLAKE_L,	&rapl_defaults_core),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) 	X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_L,		&rapl_defaults_core),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) 	X86_MATCH_INTEL_FAM6_MODEL(ICELAKE,		&rapl_defaults_core),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) 	X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_NNPI,	&rapl_defaults_core),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) 	X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_X,		&rapl_defaults_hsw_server),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) 	X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_D,		&rapl_defaults_hsw_server),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) 	X86_MATCH_INTEL_FAM6_MODEL(COMETLAKE_L,		&rapl_defaults_core),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) 	X86_MATCH_INTEL_FAM6_MODEL(COMETLAKE,		&rapl_defaults_core),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) 	X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE_L,		&rapl_defaults_core),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) 	X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE,		&rapl_defaults_core),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) 	X86_MATCH_INTEL_FAM6_MODEL(ROCKETLAKE,		&rapl_defaults_core),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) 	X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE,		&rapl_defaults_core),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) 	X86_MATCH_INTEL_FAM6_MODEL(SAPPHIRERAPIDS_X,	&rapl_defaults_spr_server),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) 	X86_MATCH_INTEL_FAM6_MODEL(LAKEFIELD,		&rapl_defaults_core),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT,	&rapl_defaults_byt),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_AIRMONT,	&rapl_defaults_cht),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT_MID,	&rapl_defaults_tng),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_AIRMONT_MID,	&rapl_defaults_ann),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT,	&rapl_defaults_core),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT_PLUS,	&rapl_defaults_core),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT_D,	&rapl_defaults_core),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT,	&rapl_defaults_core),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_D,	&rapl_defaults_core),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_L,	&rapl_defaults_core),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) 	X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNL,	&rapl_defaults_hsw_server),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) 	X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNM,	&rapl_defaults_hsw_server),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) 	{}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) MODULE_DEVICE_TABLE(x86cpu, rapl_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) /* Read once for all raw primitive data for domains */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) static void rapl_update_domain_data(struct rapl_package *rp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) 	int dmn, prim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) 	u64 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) 	for (dmn = 0; dmn < rp->nr_domains; dmn++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) 		pr_debug("update %s domain %s data\n", rp->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) 			 rp->domains[dmn].name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) 		/* exclude non-raw primitives */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) 		for (prim = 0; prim < NR_RAW_PRIMITIVES; prim++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) 			if (!rapl_read_data_raw(&rp->domains[dmn], prim,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) 						rpi[prim].unit, &val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) 				rp->domains[dmn].rdd.primitives[prim] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) static int rapl_package_register_powercap(struct rapl_package *rp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) 	struct rapl_domain *rd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) 	struct powercap_zone *power_zone = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) 	int nr_pl, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) 	/* Update the domain data of the new package */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) 	rapl_update_domain_data(rp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) 	/* first we register package domain as the parent zone */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) 	for (rd = rp->domains; rd < rp->domains + rp->nr_domains; rd++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) 		if (rd->id == RAPL_DOMAIN_PACKAGE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) 			nr_pl = find_nr_power_limit(rd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) 			pr_debug("register package domain %s\n", rp->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) 			power_zone = powercap_register_zone(&rd->power_zone,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) 					    rp->priv->control_type, rp->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) 					    NULL, &zone_ops[rd->id], nr_pl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) 					    &constraint_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) 			if (IS_ERR(power_zone)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) 				pr_debug("failed to register power zone %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) 					 rp->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) 				return PTR_ERR(power_zone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) 			/* track parent zone in per package/socket data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) 			rp->power_zone = power_zone;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) 			/* done, only one package domain per socket */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) 	if (!power_zone) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) 		pr_err("no package domain found, unknown topology!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) 	/* now register domains as children of the socket/package */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) 	for (rd = rp->domains; rd < rp->domains + rp->nr_domains; rd++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) 		struct powercap_zone *parent = rp->power_zone;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) 		if (rd->id == RAPL_DOMAIN_PACKAGE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) 		if (rd->id == RAPL_DOMAIN_PLATFORM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) 			parent = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) 		/* number of power limits per domain varies */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) 		nr_pl = find_nr_power_limit(rd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) 		power_zone = powercap_register_zone(&rd->power_zone,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) 						    rp->priv->control_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) 						    rd->name, parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) 						    &zone_ops[rd->id], nr_pl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) 						    &constraint_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) 		if (IS_ERR(power_zone)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) 			pr_debug("failed to register power_zone, %s:%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) 				 rp->name, rd->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) 			ret = PTR_ERR(power_zone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) 			goto err_cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) err_cleanup:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) 	 * Clean up previously initialized domains within the package if we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) 	 * failed after the first domain setup.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) 	while (--rd >= rp->domains) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) 		pr_debug("unregister %s domain %s\n", rp->name, rd->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) 		powercap_unregister_zone(rp->priv->control_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) 					 &rd->power_zone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) static int rapl_check_domain(int cpu, int domain, struct rapl_package *rp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) 	struct reg_action ra;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) 	switch (domain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) 	case RAPL_DOMAIN_PACKAGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) 	case RAPL_DOMAIN_PP0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) 	case RAPL_DOMAIN_PP1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) 	case RAPL_DOMAIN_DRAM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) 	case RAPL_DOMAIN_PLATFORM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) 		ra.reg = rp->priv->regs[domain][RAPL_DOMAIN_REG_STATUS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) 		pr_err("invalid domain id %d\n", domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) 	/* make sure domain counters are available and contains non-zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) 	 * values, otherwise skip it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) 	ra.mask = ENERGY_STATUS_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) 	if (rp->priv->read_raw(cpu, &ra) || !ra.value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187)  * Check if power limits are available. Two cases when they are not available:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188)  * 1. Locked by BIOS, in this case we still provide read-only access so that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189)  *    users can see what limit is set by the BIOS.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190)  * 2. Some CPUs make some domains monitoring only which means PLx MSRs may not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191)  *    exist at all. In this case, we do not show the constraints in powercap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193)  * Called after domains are detected and initialized.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) static void rapl_detect_powerlimit(struct rapl_domain *rd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) 	u64 val64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) 	/* check if the domain is locked by BIOS, ignore if MSR doesn't exist */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) 	if (!rapl_read_data_raw(rd, FW_LOCK, false, &val64)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) 		if (val64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) 			pr_info("RAPL %s domain %s locked by BIOS\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) 				rd->rp->name, rd->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) 			rd->state |= DOMAIN_STATE_BIOS_LOCKED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) 	/* check if power limit MSR exists, otherwise domain is monitoring only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) 	for (i = 0; i < NR_POWER_LIMITS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) 		int prim = rd->rpl[i].prim_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) 		if (rapl_read_data_raw(rd, prim, false, &val64))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) 			rd->rpl[i].name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) /* Detect active and valid domains for the given CPU, caller must
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218)  * ensure the CPU belongs to the targeted package and CPU hotlug is disabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) static int rapl_detect_domains(struct rapl_package *rp, int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) 	struct rapl_domain *rd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) 	for (i = 0; i < RAPL_DOMAIN_MAX; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) 		/* use physical package id to read counters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) 		if (!rapl_check_domain(cpu, i, rp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) 			rp->domain_map |= 1 << i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) 			pr_info("Found RAPL domain %s\n", rapl_domain_names[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) 	rp->nr_domains = bitmap_weight(&rp->domain_map, RAPL_DOMAIN_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) 	if (!rp->nr_domains) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) 		pr_debug("no valid rapl domains found in %s\n", rp->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) 	pr_debug("found %d domains on %s\n", rp->nr_domains, rp->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) 	rp->domains = kcalloc(rp->nr_domains + 1, sizeof(struct rapl_domain),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) 			      GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) 	if (!rp->domains)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) 	rapl_init_domains(rp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) 	for (rd = rp->domains; rd < rp->domains + rp->nr_domains; rd++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) 		rapl_detect_powerlimit(rd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) /* called from CPU hotplug notifier, hotplug lock held */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) void rapl_remove_package(struct rapl_package *rp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) 	struct rapl_domain *rd, *rd_package = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) 	package_power_limit_irq_restore(rp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) 	for (rd = rp->domains; rd < rp->domains + rp->nr_domains; rd++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) 		rapl_write_data_raw(rd, PL1_ENABLE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) 		rapl_write_data_raw(rd, PL1_CLAMP, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) 		if (find_nr_power_limit(rd) > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) 			rapl_write_data_raw(rd, PL2_ENABLE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) 			rapl_write_data_raw(rd, PL2_CLAMP, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) 			rapl_write_data_raw(rd, PL4_ENABLE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) 		if (rd->id == RAPL_DOMAIN_PACKAGE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) 			rd_package = rd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) 		pr_debug("remove package, undo power limit on %s: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) 			 rp->name, rd->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) 		powercap_unregister_zone(rp->priv->control_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) 					 &rd->power_zone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) 	/* do parent zone last */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) 	powercap_unregister_zone(rp->priv->control_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) 				 &rd_package->power_zone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) 	list_del(&rp->plist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) 	kfree(rp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) EXPORT_SYMBOL_GPL(rapl_remove_package);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) /* caller to ensure CPU hotplug lock is held */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) struct rapl_package *rapl_find_package_domain(int cpu, struct rapl_if_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) 	int id = topology_logical_die_id(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) 	struct rapl_package *rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) 	list_for_each_entry(rp, &rapl_packages, plist) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) 		if (rp->id == id
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) 		    && rp->priv->control_type == priv->control_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) 			return rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) EXPORT_SYMBOL_GPL(rapl_find_package_domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) /* called from CPU hotplug notifier, hotplug lock held */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) struct rapl_package *rapl_add_package(int cpu, struct rapl_if_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) 	int id = topology_logical_die_id(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) 	struct rapl_package *rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) 	struct cpuinfo_x86 *c = &cpu_data(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) 	if (!rapl_defaults)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) 		return ERR_PTR(-ENODEV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) 	rp = kzalloc(sizeof(struct rapl_package), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) 	if (!rp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) 		return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) 	/* add the new package to the list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) 	rp->id = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) 	rp->lead_cpu = cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) 	rp->priv = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) 	if (topology_max_die_per_package() > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) 		snprintf(rp->name, PACKAGE_DOMAIN_NAME_LENGTH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) 			 "package-%d-die-%d", c->phys_proc_id, c->cpu_die_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) 		snprintf(rp->name, PACKAGE_DOMAIN_NAME_LENGTH, "package-%d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) 			 c->phys_proc_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) 	/* check if the package contains valid domains */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) 	if (rapl_detect_domains(rp, cpu) || rapl_defaults->check_unit(rp, cpu)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) 		ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) 		goto err_free_package;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) 	ret = rapl_package_register_powercap(rp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) 	if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) 		INIT_LIST_HEAD(&rp->plist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) 		list_add(&rp->plist, &rapl_packages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) 		return rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) err_free_package:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) 	kfree(rp->domains);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) 	kfree(rp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) 	return ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) EXPORT_SYMBOL_GPL(rapl_add_package);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) static void power_limit_state_save(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) 	struct rapl_package *rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) 	struct rapl_domain *rd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) 	int nr_pl, ret, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) 	get_online_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) 	list_for_each_entry(rp, &rapl_packages, plist) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) 		if (!rp->power_zone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) 		rd = power_zone_to_rapl_domain(rp->power_zone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) 		nr_pl = find_nr_power_limit(rd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) 		for (i = 0; i < nr_pl; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) 			switch (rd->rpl[i].prim_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) 			case PL1_ENABLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) 				ret = rapl_read_data_raw(rd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) 						 POWER_LIMIT1, true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) 						 &rd->rpl[i].last_power_limit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) 				if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) 					rd->rpl[i].last_power_limit = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) 			case PL2_ENABLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) 				ret = rapl_read_data_raw(rd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) 						 POWER_LIMIT2, true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) 						 &rd->rpl[i].last_power_limit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) 				if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) 					rd->rpl[i].last_power_limit = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) 			case PL4_ENABLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) 				ret = rapl_read_data_raw(rd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) 						 POWER_LIMIT4, true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) 						 &rd->rpl[i].last_power_limit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) 				if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) 					rd->rpl[i].last_power_limit = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) 	put_online_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) static void power_limit_state_restore(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) 	struct rapl_package *rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) 	struct rapl_domain *rd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) 	int nr_pl, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) 	get_online_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) 	list_for_each_entry(rp, &rapl_packages, plist) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) 		if (!rp->power_zone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) 		rd = power_zone_to_rapl_domain(rp->power_zone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) 		nr_pl = find_nr_power_limit(rd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) 		for (i = 0; i < nr_pl; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) 			switch (rd->rpl[i].prim_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) 			case PL1_ENABLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) 				if (rd->rpl[i].last_power_limit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) 					rapl_write_data_raw(rd, POWER_LIMIT1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) 					    rd->rpl[i].last_power_limit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) 			case PL2_ENABLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) 				if (rd->rpl[i].last_power_limit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) 					rapl_write_data_raw(rd, POWER_LIMIT2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) 					    rd->rpl[i].last_power_limit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) 			case PL4_ENABLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) 				if (rd->rpl[i].last_power_limit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) 					rapl_write_data_raw(rd, POWER_LIMIT4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) 					    rd->rpl[i].last_power_limit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) 	put_online_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) static int rapl_pm_callback(struct notifier_block *nb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) 			    unsigned long mode, void *_unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) 	switch (mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) 	case PM_SUSPEND_PREPARE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) 		power_limit_state_save();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) 	case PM_POST_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) 		power_limit_state_restore();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) 	return NOTIFY_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) static struct notifier_block rapl_pm_notifier = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) 	.notifier_call = rapl_pm_callback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) static struct platform_device *rapl_msr_platdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) static int __init rapl_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) 	const struct x86_cpu_id *id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) 	id = x86_match_cpu(rapl_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) 	if (!id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) 		pr_err("driver does not support CPU family %d model %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) 		       boot_cpu_data.x86, boot_cpu_data.x86_model);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) 	rapl_defaults = (struct rapl_defaults *)id->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) 	ret = register_pm_notifier(&rapl_pm_notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) 	rapl_msr_platdev = platform_device_alloc("intel_rapl_msr", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) 	if (!rapl_msr_platdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) 		ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) 		goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) 	ret = platform_device_add(rapl_msr_platdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) 		platform_device_put(rapl_msr_platdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) 		unregister_pm_notifier(&rapl_pm_notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) static void __exit rapl_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) 	platform_device_unregister(rapl_msr_platdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) 	unregister_pm_notifier(&rapl_pm_notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) fs_initcall(rapl_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) module_exit(rapl_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) MODULE_DESCRIPTION("Intel Runtime Average Power Limit (RAPL) common code");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) MODULE_AUTHOR("Jacob Pan <jacob.jun.pan@intel.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) MODULE_LICENSE("GPL v2");