^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");