From 68f7313071f9d3409f144f4fa33069bd846df6c3 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Mon, 17 Jun 2024 09:04:34 +0300 Subject: [PATCH 01/10] platform/x86/intel-uncore-freq: Re-arrange bit masks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ANBZ: #21537 commit 36f70045528f5639bb50b3b74c7925943cf6983a upstream. Rename the various bitmasks from the 'UNCORE_GENMASK_*' to 'UNCORE_*_MASK', and re-order them based on the register they reside in. No functional change intended. Intel-SIG: commit 36f70045528f platform/x86/intel-uncore-freq: Re-arrange bit masks. Backport intel uncore-freq driver update from 6.11 Signed-off-by: Tero Kristo Reviewed-by: Ilpo Järvinen Acked-by: Srinivas Pandruvada Link: https://lore.kernel.org/r/20240617060708.892981-2-tero.kristo@linux.intel.com Signed-off-by: Ilpo Järvinen [ Yingbao Jia: amend commit log ] Signed-off-by: Yingbao Jia --- .../x86/intel-uncore-frequency-tpmi.c | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/drivers/platform/x86/intel-uncore-frequency-tpmi.c b/drivers/platform/x86/intel-uncore-frequency-tpmi.c index 24ebe3336259..c551e24a31a4 100644 --- a/drivers/platform/x86/intel-uncore-frequency-tpmi.c +++ b/drivers/platform/x86/intel-uncore-frequency-tpmi.c @@ -69,9 +69,12 @@ struct tpmi_uncore_struct { bool write_blocked; }; -#define UNCORE_GENMASK_MIN_RATIO GENMASK_ULL(21, 15) -#define UNCORE_GENMASK_MAX_RATIO GENMASK_ULL(14, 8) -#define UNCORE_GENMASK_CURRENT_RATIO GENMASK_ULL(6, 0) +/* Bit definitions for STATUS register */ +#define UNCORE_CURRENT_RATIO_MASK GENMASK_ULL(6, 0) + +/* Bit definitions for CONTROL register */ +#define UNCORE_MAX_RATIO_MASK GENMASK_ULL(14, 8) +#define UNCORE_MIN_RATIO_MASK GENMASK_ULL(21, 15) /* Helper function to read MMIO offset for max/min control frequency */ static void read_control_freq(struct tpmi_uncore_cluster_info *cluster_info, @@ -80,11 +83,11 @@ static void read_control_freq(struct tpmi_uncore_cluster_info *cluster_info, u64 control; control = readq(cluster_info->cluster_base + UNCORE_CONTROL_INDEX); - *max = FIELD_GET(UNCORE_GENMASK_MAX_RATIO, control) * UNCORE_FREQ_KHZ_MULTIPLIER; - *min = FIELD_GET(UNCORE_GENMASK_MIN_RATIO, control) * UNCORE_FREQ_KHZ_MULTIPLIER; + *max = FIELD_GET(UNCORE_MAX_RATIO_MASK, control) * UNCORE_FREQ_KHZ_MULTIPLIER; + *min = FIELD_GET(UNCORE_MIN_RATIO_MASK, control) * UNCORE_FREQ_KHZ_MULTIPLIER; } -#define UNCORE_MAX_RATIO FIELD_MAX(UNCORE_GENMASK_MAX_RATIO) +#define UNCORE_MAX_RATIO FIELD_MAX(UNCORE_MAX_RATIO_MASK) /* Callback for sysfs read for max/min frequencies. Called under mutex locks */ static int uncore_read_control_freq(struct uncore_data *data, unsigned int *min, @@ -134,11 +137,11 @@ static void write_control_freq(struct tpmi_uncore_cluster_info *cluster_info, un control = readq(cluster_info->cluster_base + UNCORE_CONTROL_INDEX); if (min_max) { - control &= ~UNCORE_GENMASK_MAX_RATIO; - control |= FIELD_PREP(UNCORE_GENMASK_MAX_RATIO, input); + control &= ~UNCORE_MAX_RATIO_MASK; + control |= FIELD_PREP(UNCORE_MAX_RATIO_MASK, input); } else { - control &= ~UNCORE_GENMASK_MIN_RATIO; - control |= FIELD_PREP(UNCORE_GENMASK_MIN_RATIO, input); + control &= ~UNCORE_MIN_RATIO_MASK; + control |= FIELD_PREP(UNCORE_MIN_RATIO_MASK, input); } writeq(control, (cluster_info->cluster_base + UNCORE_CONTROL_INDEX)); @@ -204,7 +207,7 @@ static int uncore_read_freq(struct uncore_data *data, unsigned int *freq) return -ENODATA; status = readq((u8 __iomem *)cluster_info->cluster_base + UNCORE_STATUS_INDEX); - *freq = FIELD_GET(UNCORE_GENMASK_CURRENT_RATIO, status) * UNCORE_FREQ_KHZ_MULTIPLIER; + *freq = FIELD_GET(UNCORE_CURRENT_RATIO_MASK, status) * UNCORE_FREQ_KHZ_MULTIPLIER; return 0; } -- Gitee From 8821cecf3755e1ce5086ec91c85e8d58766a1668 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Mon, 17 Jun 2024 09:04:35 +0300 Subject: [PATCH 02/10] platform/x86/intel-uncore-freq: Get rid of magic values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ANBZ: #21537 commit 4babdbdce6a05ae6f228c1ae1e61a4bc91a91d33 upstream. Get rid of any magic bitmasks from the code. Define proper macros for these, and use the bitfield operations to access them. No functional change intended. Intel-SIG: commit 4babdbdce6a0 platform/x86/intel-uncore-freq: Get rid of magic values. Backport intel uncore-freq driver update from 6.11 Signed-off-by: Tero Kristo Acked-by: Srinivas Pandruvada Link: https://lore.kernel.org/r/20240617060708.892981-3-tero.kristo@linux.intel.com Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen [ Yingbao Jia: amend commit log ] Signed-off-by: Yingbao Jia --- drivers/platform/x86/intel-uncore-frequency.c | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/drivers/platform/x86/intel-uncore-frequency.c b/drivers/platform/x86/intel-uncore-frequency.c index 730661560f24..2ee07f75f287 100644 --- a/drivers/platform/x86/intel-uncore-frequency.c +++ b/drivers/platform/x86/intel-uncore-frequency.c @@ -14,6 +14,7 @@ * Author: Srinivas Pandruvada */ +#include #include #include #include @@ -36,6 +37,11 @@ static enum cpuhp_state uncore_hp_state __read_mostly; #define MSR_UNCORE_PERF_STATUS 0x621 #define UNCORE_FREQ_KHZ_MULTIPLIER 100000 +#define UNCORE_MAX_RATIO_MASK GENMASK_ULL(6, 0) +#define UNCORE_MIN_RATIO_MASK GENMASK_ULL(14, 8) + +#define UNCORE_CURRENT_RATIO_MASK GENMASK_ULL(6, 0) + static int uncore_read_control_freq(struct uncore_data *data, unsigned int *min, unsigned int *max) { @@ -49,8 +55,8 @@ static int uncore_read_control_freq(struct uncore_data *data, unsigned int *min, if (ret) return ret; - *max = (cap & 0x7F) * UNCORE_FREQ_KHZ_MULTIPLIER; - *min = ((cap & GENMASK(14, 8)) >> 8) * UNCORE_FREQ_KHZ_MULTIPLIER; + *max = FIELD_GET(UNCORE_MAX_RATIO_MASK, cap) * UNCORE_FREQ_KHZ_MULTIPLIER; + *min = FIELD_GET(UNCORE_MIN_RATIO_MASK, cap) * UNCORE_FREQ_KHZ_MULTIPLIER; return 0; } @@ -62,7 +68,7 @@ static int uncore_write_control_freq(struct uncore_data *data, unsigned int inpu u64 cap; input /= UNCORE_FREQ_KHZ_MULTIPLIER; - if (!input || input > 0x7F) + if (!input || input > FIELD_MAX(UNCORE_MAX_RATIO_MASK)) return -EINVAL; if (data->control_cpu < 0) @@ -73,11 +79,11 @@ static int uncore_write_control_freq(struct uncore_data *data, unsigned int inpu return ret; if (min_max) { - cap &= ~0x7F; - cap |= input; + cap &= ~UNCORE_MAX_RATIO_MASK; + cap |= FIELD_PREP(UNCORE_MAX_RATIO_MASK, input); } else { - cap &= ~GENMASK(14, 8); - cap |= (input << 8); + cap &= ~UNCORE_MIN_RATIO_MASK; + cap |= FIELD_PREP(UNCORE_MIN_RATIO_MASK, input); } ret = wrmsrl_on_cpu(data->control_cpu, MSR_UNCORE_RATIO_LIMIT, cap); @@ -101,7 +107,7 @@ static int uncore_read_freq(struct uncore_data *data, unsigned int *freq) if (ret) return ret; - *freq = (ratio & 0x7F) * UNCORE_FREQ_KHZ_MULTIPLIER; + *freq = FIELD_GET(UNCORE_CURRENT_RATIO_MASK, ratio) * UNCORE_FREQ_KHZ_MULTIPLIER; return 0; } -- Gitee From c7a63facda6effaa2cd19a5d2fb07897424121a8 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Mon, 17 Jun 2024 09:04:36 +0300 Subject: [PATCH 03/10] platform/x86/intel-uncore-freq: Get rid of magic min_max argument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ANBZ: #21537 commit 90583374f1a0951d563de50aeac6357b724d08f6 upstream. Get rid of the hardcoded / magic min_max argument from internal APIs. Instead, use an enumerated index value for it. No functional change intended. Intel-SIG: commit 90583374f1a0 platform/x86/intel-uncore-freq: Get rid of magic min_max argument. Backport intel uncore-freq driver update from 6.11 Signed-off-by: Tero Kristo Acked-by: Srinivas Pandruvada Link: https://lore.kernel.org/r/20240617060708.892981-4-tero.kristo@linux.intel.com Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen [ Yingbao Jia: amend commit log ] Signed-off-by: Yingbao Jia --- .../x86/intel-uncore-frequency-common.c | 21 ++++++++++--------- .../x86/intel-uncore-frequency-common.h | 8 ++++++- .../x86/intel-uncore-frequency-tpmi.c | 18 +++++++++------- drivers/platform/x86/intel-uncore-frequency.c | 4 ++-- 4 files changed, 30 insertions(+), 21 deletions(-) diff --git a/drivers/platform/x86/intel-uncore-frequency-common.c b/drivers/platform/x86/intel-uncore-frequency-common.c index db92d1b16f2f..cc7a795c12f7 100644 --- a/drivers/platform/x86/intel-uncore-frequency-common.c +++ b/drivers/platform/x86/intel-uncore-frequency-common.c @@ -20,7 +20,7 @@ static DEFINE_IDA(intel_uncore_ida); /* callbacks for actual HW read/write */ static int (*uncore_read)(struct uncore_data *data, unsigned int *min, unsigned int *max); -static int (*uncore_write)(struct uncore_data *data, unsigned int input, unsigned int min_max); +static int (*uncore_write)(struct uncore_data *data, unsigned int input, enum uncore_index index); static int (*uncore_read_freq)(struct uncore_data *data, unsigned int *freq); static ssize_t show_domain_id(struct kobject *kobj, struct kobj_attribute *attr, char *buf) @@ -45,7 +45,7 @@ static ssize_t show_package_id(struct kobject *kobj, struct kobj_attribute *attr } static ssize_t show_min_max_freq_khz(struct uncore_data *data, - char *buf, int min_max) + char *buf, enum uncore_index index) { unsigned int min, max; int ret; @@ -56,7 +56,7 @@ static ssize_t show_min_max_freq_khz(struct uncore_data *data, if (ret) return ret; - if (min_max) + if (index == UNCORE_INDEX_MAX_FREQ) return sprintf(buf, "%u\n", max); return sprintf(buf, "%u\n", min); @@ -64,7 +64,7 @@ static ssize_t show_min_max_freq_khz(struct uncore_data *data, static ssize_t store_min_max_freq_khz(struct uncore_data *data, const char *buf, ssize_t count, - int min_max) + enum uncore_index index) { unsigned int input; int ret; @@ -73,7 +73,7 @@ static ssize_t store_min_max_freq_khz(struct uncore_data *data, return -EINVAL; mutex_lock(&uncore_lock); - ret = uncore_write(data, input, min_max); + ret = uncore_write(data, input, index); mutex_unlock(&uncore_lock); if (ret) @@ -125,11 +125,11 @@ static ssize_t show_perf_status_freq_khz(struct uncore_data *data, char *buf) return show_perf_status_freq_khz(data, buf); \ } -store_uncore_min_max(min_freq_khz, 0); -store_uncore_min_max(max_freq_khz, 1); +store_uncore_min_max(min_freq_khz, UNCORE_INDEX_MIN_FREQ); +store_uncore_min_max(max_freq_khz, UNCORE_INDEX_MAX_FREQ); -show_uncore_min_max(min_freq_khz, 0); -show_uncore_min_max(max_freq_khz, 1); +show_uncore_min_max(min_freq_khz, UNCORE_INDEX_MIN_FREQ); +show_uncore_min_max(max_freq_khz, UNCORE_INDEX_MAX_FREQ); show_uncore_perf_status(current_freq_khz); @@ -270,7 +270,8 @@ void uncore_freq_remove_die_entry(struct uncore_data *data) EXPORT_SYMBOL_NS_GPL(uncore_freq_remove_die_entry, INTEL_UNCORE_FREQUENCY); int uncore_freq_common_init(int (*read_control_freq)(struct uncore_data *data, unsigned int *min, unsigned int *max), - int (*write_control_freq)(struct uncore_data *data, unsigned int input, unsigned int set_max), + int (*write_control_freq)(struct uncore_data *data, unsigned int input, + enum uncore_index index), int (*read_freq)(struct uncore_data *data, unsigned int *freq)) { mutex_lock(&uncore_lock); diff --git a/drivers/platform/x86/intel-uncore-frequency-common.h b/drivers/platform/x86/intel-uncore-frequency-common.h index 0e5bf507e555..c6ceeda3f2bf 100644 --- a/drivers/platform/x86/intel-uncore-frequency-common.h +++ b/drivers/platform/x86/intel-uncore-frequency-common.h @@ -66,8 +66,14 @@ struct uncore_data { #define UNCORE_DOMAIN_ID_INVALID -1 +enum uncore_index { + UNCORE_INDEX_MIN_FREQ, + UNCORE_INDEX_MAX_FREQ, +}; + int uncore_freq_common_init(int (*read_control_freq)(struct uncore_data *data, unsigned int *min, unsigned int *max), - int (*write_control_freq)(struct uncore_data *data, unsigned int input, unsigned int min_max), + int (*write_control_freq)(struct uncore_data *data, unsigned int input, + enum uncore_index index), int (*uncore_read_freq)(struct uncore_data *data, unsigned int *freq)); void uncore_freq_common_exit(void); int uncore_freq_add_entry(struct uncore_data *data, int cpu); diff --git a/drivers/platform/x86/intel-uncore-frequency-tpmi.c b/drivers/platform/x86/intel-uncore-frequency-tpmi.c index c551e24a31a4..ef43493110ec 100644 --- a/drivers/platform/x86/intel-uncore-frequency-tpmi.c +++ b/drivers/platform/x86/intel-uncore-frequency-tpmi.c @@ -130,13 +130,13 @@ static int uncore_read_control_freq(struct uncore_data *data, unsigned int *min, /* Helper function to write MMIO offset for max/min control frequency */ static void write_control_freq(struct tpmi_uncore_cluster_info *cluster_info, unsigned int input, - unsigned int min_max) + unsigned int index) { u64 control; control = readq(cluster_info->cluster_base + UNCORE_CONTROL_INDEX); - if (min_max) { + if (index == UNCORE_INDEX_MAX_FREQ) { control &= ~UNCORE_MAX_RATIO_MASK; control |= FIELD_PREP(UNCORE_MAX_RATIO_MASK, input); } else { @@ -149,7 +149,7 @@ static void write_control_freq(struct tpmi_uncore_cluster_info *cluster_info, un /* Callback for sysfs write for max/min frequencies. Called under mutex locks */ static int uncore_write_control_freq(struct uncore_data *data, unsigned int input, - unsigned int min_max) + enum uncore_index index) { struct tpmi_uncore_cluster_info *cluster_info; struct tpmi_uncore_struct *uncore_root; @@ -174,10 +174,10 @@ static int uncore_write_control_freq(struct uncore_data *data, unsigned int inpu for (j = 0; j < uncore_root->pd_info[i].cluster_count; ++j) write_control_freq(&uncore_root->pd_info[i].cluster_infos[j], - input, min_max); + input, index); } - if (min_max) + if (index == UNCORE_INDEX_MAX_FREQ) uncore_root->max_ratio = input; else uncore_root->min_ratio = input; @@ -185,13 +185,15 @@ static int uncore_write_control_freq(struct uncore_data *data, unsigned int inpu return 0; } - if (min_max && uncore_root->max_ratio && uncore_root->max_ratio < input) + if (index == UNCORE_INDEX_MAX_FREQ && uncore_root->max_ratio && + uncore_root->max_ratio < input) return -EINVAL; - if (!min_max && uncore_root->min_ratio && uncore_root->min_ratio > input) + if (index == UNCORE_INDEX_MIN_FREQ && uncore_root->min_ratio && + uncore_root->min_ratio > input) return -EINVAL; - write_control_freq(cluster_info, input, min_max); + write_control_freq(cluster_info, input, index); return 0; } diff --git a/drivers/platform/x86/intel-uncore-frequency.c b/drivers/platform/x86/intel-uncore-frequency.c index 2ee07f75f287..7c8c2eaae6c5 100644 --- a/drivers/platform/x86/intel-uncore-frequency.c +++ b/drivers/platform/x86/intel-uncore-frequency.c @@ -62,7 +62,7 @@ static int uncore_read_control_freq(struct uncore_data *data, unsigned int *min, } static int uncore_write_control_freq(struct uncore_data *data, unsigned int input, - unsigned int min_max) + enum uncore_index index) { int ret; u64 cap; @@ -78,7 +78,7 @@ static int uncore_write_control_freq(struct uncore_data *data, unsigned int inpu if (ret) return ret; - if (min_max) { + if (index == UNCORE_INDEX_MAX_FREQ) { cap &= ~UNCORE_MAX_RATIO_MASK; cap |= FIELD_PREP(UNCORE_MAX_RATIO_MASK, input); } else { -- Gitee From f5eaff0471216e0a4c4b9385716a0d17ae820099 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Mon, 17 Jun 2024 09:04:37 +0300 Subject: [PATCH 04/10] platform/x86/intel-uncore-freq: Use uncore_index with read_control_freq MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ANBZ: #21537 commit 69207a0f17d4e5a9bdd9feeece26a84add305157 upstream. Use the enumerated index for selecting the uncore driver parameter to read, instead of reading everything. This is done in preparation to expand the API to access more parameters later. No functional change intended. Intel-SIG: commit 69207a0f17d4 platform/x86/intel-uncore-freq: Use uncore_index with read_control_freq. Backport intel uncore-freq driver update from 6.11 Signed-off-by: Tero Kristo Acked-by: Srinivas Pandruvada Link: https://lore.kernel.org/r/20240617060708.892981-5-tero.kristo@linux.intel.com [ij: Removed underscores from variable names] Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen [ Yingbao Jia: amend commit log ] Signed-off-by: Yingbao Jia --- .../x86/intel-uncore-frequency-common.c | 23 ++++++------ .../x86/intel-uncore-frequency-common.h | 9 +++-- .../x86/intel-uncore-frequency-tpmi.c | 37 ++++++++++++------- drivers/platform/x86/intel-uncore-frequency.c | 10 +++-- 4 files changed, 45 insertions(+), 34 deletions(-) diff --git a/drivers/platform/x86/intel-uncore-frequency-common.c b/drivers/platform/x86/intel-uncore-frequency-common.c index cc7a795c12f7..3c98987a59b1 100644 --- a/drivers/platform/x86/intel-uncore-frequency-common.c +++ b/drivers/platform/x86/intel-uncore-frequency-common.c @@ -19,7 +19,7 @@ static int uncore_instance_count; static DEFINE_IDA(intel_uncore_ida); /* callbacks for actual HW read/write */ -static int (*uncore_read)(struct uncore_data *data, unsigned int *min, unsigned int *max); +static int (*uncore_read)(struct uncore_data *data, unsigned int *value, enum uncore_index index); static int (*uncore_write)(struct uncore_data *data, unsigned int input, enum uncore_index index); static int (*uncore_read_freq)(struct uncore_data *data, unsigned int *freq); @@ -47,19 +47,16 @@ static ssize_t show_package_id(struct kobject *kobj, struct kobj_attribute *attr static ssize_t show_min_max_freq_khz(struct uncore_data *data, char *buf, enum uncore_index index) { - unsigned int min, max; + unsigned int value; int ret; mutex_lock(&uncore_lock); - ret = uncore_read(data, &min, &max); + ret = uncore_read(data, &value, index); mutex_unlock(&uncore_lock); if (ret) return ret; - if (index == UNCORE_INDEX_MAX_FREQ) - return sprintf(buf, "%u\n", max); - - return sprintf(buf, "%u\n", min); + return sprintf(buf, "%u\n", value); } static ssize_t store_min_max_freq_khz(struct uncore_data *data, @@ -238,7 +235,8 @@ int uncore_freq_add_entry(struct uncore_data *data, int cpu) sprintf(data->name, "package_%02d_die_%02d", data->package_id, data->die_id); } - uncore_read(data, &data->initial_min_freq_khz, &data->initial_max_freq_khz); + uncore_read(data, &data->initial_min_freq_khz, UNCORE_INDEX_MIN_FREQ); + uncore_read(data, &data->initial_max_freq_khz, UNCORE_INDEX_MAX_FREQ); ret = create_attr_group(data, data->name); if (ret) { @@ -269,10 +267,11 @@ void uncore_freq_remove_die_entry(struct uncore_data *data) } EXPORT_SYMBOL_NS_GPL(uncore_freq_remove_die_entry, INTEL_UNCORE_FREQUENCY); -int uncore_freq_common_init(int (*read_control_freq)(struct uncore_data *data, unsigned int *min, unsigned int *max), - int (*write_control_freq)(struct uncore_data *data, unsigned int input, - enum uncore_index index), - int (*read_freq)(struct uncore_data *data, unsigned int *freq)) +int uncore_freq_common_init(int (*read_control_freq)(struct uncore_data *data, unsigned int *value, + enum uncore_index index), + int (*write_control_freq)(struct uncore_data *data, unsigned int input, + enum uncore_index index), + int (*read_freq)(struct uncore_data *data, unsigned int *freq)) { mutex_lock(&uncore_lock); diff --git a/drivers/platform/x86/intel-uncore-frequency-common.h b/drivers/platform/x86/intel-uncore-frequency-common.h index c6ceeda3f2bf..2d98931cd8e2 100644 --- a/drivers/platform/x86/intel-uncore-frequency-common.h +++ b/drivers/platform/x86/intel-uncore-frequency-common.h @@ -71,10 +71,11 @@ enum uncore_index { UNCORE_INDEX_MAX_FREQ, }; -int uncore_freq_common_init(int (*read_control_freq)(struct uncore_data *data, unsigned int *min, unsigned int *max), - int (*write_control_freq)(struct uncore_data *data, unsigned int input, - enum uncore_index index), - int (*uncore_read_freq)(struct uncore_data *data, unsigned int *freq)); +int uncore_freq_common_init(int (*read_control_freq)(struct uncore_data *data, unsigned int *value, + enum uncore_index index), + int (*write_control_freq)(struct uncore_data *data, unsigned int input, + enum uncore_index index), + int (*uncore_read_freq)(struct uncore_data *data, unsigned int *freq)); void uncore_freq_common_exit(void); int uncore_freq_add_entry(struct uncore_data *data, int cpu); void uncore_freq_remove_die_entry(struct uncore_data *data); diff --git a/drivers/platform/x86/intel-uncore-frequency-tpmi.c b/drivers/platform/x86/intel-uncore-frequency-tpmi.c index ef43493110ec..77425a226687 100644 --- a/drivers/platform/x86/intel-uncore-frequency-tpmi.c +++ b/drivers/platform/x86/intel-uncore-frequency-tpmi.c @@ -78,20 +78,22 @@ struct tpmi_uncore_struct { /* Helper function to read MMIO offset for max/min control frequency */ static void read_control_freq(struct tpmi_uncore_cluster_info *cluster_info, - unsigned int *min, unsigned int *max) + unsigned int *value, enum uncore_index index) { u64 control; control = readq(cluster_info->cluster_base + UNCORE_CONTROL_INDEX); - *max = FIELD_GET(UNCORE_MAX_RATIO_MASK, control) * UNCORE_FREQ_KHZ_MULTIPLIER; - *min = FIELD_GET(UNCORE_MIN_RATIO_MASK, control) * UNCORE_FREQ_KHZ_MULTIPLIER; + if (index == UNCORE_INDEX_MAX_FREQ) + *value = FIELD_GET(UNCORE_MAX_RATIO_MASK, control) * UNCORE_FREQ_KHZ_MULTIPLIER; + else + *value = FIELD_GET(UNCORE_MIN_RATIO_MASK, control) * UNCORE_FREQ_KHZ_MULTIPLIER; } #define UNCORE_MAX_RATIO FIELD_MAX(UNCORE_MAX_RATIO_MASK) /* Callback for sysfs read for max/min frequencies. Called under mutex locks */ -static int uncore_read_control_freq(struct uncore_data *data, unsigned int *min, - unsigned int *max) +static int uncore_read_control_freq(struct uncore_data *data, unsigned int *value, + enum uncore_index index) { struct tpmi_uncore_cluster_info *cluster_info; @@ -99,10 +101,11 @@ static int uncore_read_control_freq(struct uncore_data *data, unsigned int *min, if (cluster_info->root_domain) { struct tpmi_uncore_struct *uncore_root = cluster_info->uncore_root; - int i, _min = 0, _max = 0; + unsigned int min, max, v; + int i; - *min = UNCORE_MAX_RATIO * UNCORE_FREQ_KHZ_MULTIPLIER; - *max = 0; + min = UNCORE_MAX_RATIO * UNCORE_FREQ_KHZ_MULTIPLIER; + max = 0; /* * Get the max/min by looking at each cluster. Get the lowest @@ -113,17 +116,23 @@ static int uncore_read_control_freq(struct uncore_data *data, unsigned int *min, for (j = 0; j < uncore_root->pd_info[i].cluster_count; ++j) { read_control_freq(&uncore_root->pd_info[i].cluster_infos[j], - &_min, &_max); - if (*min > _min) - *min = _min; - if (*max < _max) - *max = _max; + &v, index); + if (v < min) + min = v; + if (v > max) + max = v; } } + + if (index == UNCORE_INDEX_MIN_FREQ) + *value = min; + else + *value = max; + return 0; } - read_control_freq(cluster_info, min, max); + read_control_freq(cluster_info, value, index); return 0; } diff --git a/drivers/platform/x86/intel-uncore-frequency.c b/drivers/platform/x86/intel-uncore-frequency.c index 7c8c2eaae6c5..dd0e950c1d03 100644 --- a/drivers/platform/x86/intel-uncore-frequency.c +++ b/drivers/platform/x86/intel-uncore-frequency.c @@ -42,8 +42,8 @@ static enum cpuhp_state uncore_hp_state __read_mostly; #define UNCORE_CURRENT_RATIO_MASK GENMASK_ULL(6, 0) -static int uncore_read_control_freq(struct uncore_data *data, unsigned int *min, - unsigned int *max) +static int uncore_read_control_freq(struct uncore_data *data, unsigned int *value, + enum uncore_index index) { u64 cap; int ret; @@ -55,8 +55,10 @@ static int uncore_read_control_freq(struct uncore_data *data, unsigned int *min, if (ret) return ret; - *max = FIELD_GET(UNCORE_MAX_RATIO_MASK, cap) * UNCORE_FREQ_KHZ_MULTIPLIER; - *min = FIELD_GET(UNCORE_MIN_RATIO_MASK, cap) * UNCORE_FREQ_KHZ_MULTIPLIER; + if (index == UNCORE_INDEX_MAX_FREQ) + *value = FIELD_GET(UNCORE_MAX_RATIO_MASK, cap) * UNCORE_FREQ_KHZ_MULTIPLIER; + else + *value = FIELD_GET(UNCORE_MIN_RATIO_MASK, cap) * UNCORE_FREQ_KHZ_MULTIPLIER; return 0; } -- Gitee From eddf468de43fbeadabb077b1ef1a540c19204661 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Mon, 17 Jun 2024 09:04:38 +0300 Subject: [PATCH 05/10] platform/x86/intel-uncore-freq: Get rid of uncore_read_freq driver API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ANBZ: #21537 commit d766abfbea9c8f2e7c87c59a572a1ae7f7ee5909 upstream. Get rid of uncore_read_freq driver API. Instead, add a new entry to the enumerated read interface and use this. No functional change intended. Intel-SIG: commit d766abfbea9c platform/x86/intel-uncore-freq: Get rid of uncore_read_freq driver API. Backport intel uncore-freq driver update from 6.11 Signed-off-by: Tero Kristo Acked-by: Srinivas Pandruvada Link: https://lore.kernel.org/r/20240617060708.892981-6-tero.kristo@linux.intel.com Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen [ Yingbao Jia: amend commit log ] Signed-off-by: Yingbao Jia --- .../x86/intel-uncore-frequency-common.c | 19 ++++++-------- .../x86/intel-uncore-frequency-common.h | 10 ++++---- .../x86/intel-uncore-frequency-tpmi.c | 25 ++++++++++++++++--- drivers/platform/x86/intel-uncore-frequency.c | 20 +++++++++++++-- 4 files changed, 52 insertions(+), 22 deletions(-) diff --git a/drivers/platform/x86/intel-uncore-frequency-common.c b/drivers/platform/x86/intel-uncore-frequency-common.c index 3c98987a59b1..86e3758820fc 100644 --- a/drivers/platform/x86/intel-uncore-frequency-common.c +++ b/drivers/platform/x86/intel-uncore-frequency-common.c @@ -21,7 +21,6 @@ static DEFINE_IDA(intel_uncore_ida); /* callbacks for actual HW read/write */ static int (*uncore_read)(struct uncore_data *data, unsigned int *value, enum uncore_index index); static int (*uncore_write)(struct uncore_data *data, unsigned int input, enum uncore_index index); -static int (*uncore_read_freq)(struct uncore_data *data, unsigned int *freq); static ssize_t show_domain_id(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { @@ -85,7 +84,7 @@ static ssize_t show_perf_status_freq_khz(struct uncore_data *data, char *buf) int ret; mutex_lock(&uncore_lock); - ret = uncore_read_freq(data, &freq); + ret = uncore_read(data, &freq, UNCORE_INDEX_CURRENT_FREQ); mutex_unlock(&uncore_lock); if (ret) return ret; @@ -195,7 +194,7 @@ static int create_attr_group(struct uncore_data *data, char *name) data->uncore_attrs[index++] = &data->initial_min_freq_khz_kobj_attr.attr; data->uncore_attrs[index++] = &data->initial_max_freq_khz_kobj_attr.attr; - ret = uncore_read_freq(data, &freq); + ret = uncore_read(data, &freq, UNCORE_INDEX_CURRENT_FREQ); if (!ret) data->uncore_attrs[index++] = &data->current_freq_khz_kobj_attr.attr; @@ -267,17 +266,15 @@ void uncore_freq_remove_die_entry(struct uncore_data *data) } EXPORT_SYMBOL_NS_GPL(uncore_freq_remove_die_entry, INTEL_UNCORE_FREQUENCY); -int uncore_freq_common_init(int (*read_control_freq)(struct uncore_data *data, unsigned int *value, - enum uncore_index index), - int (*write_control_freq)(struct uncore_data *data, unsigned int input, - enum uncore_index index), - int (*read_freq)(struct uncore_data *data, unsigned int *freq)) +int uncore_freq_common_init(int (*read)(struct uncore_data *data, unsigned int *value, + enum uncore_index index), + int (*write)(struct uncore_data *data, unsigned int input, + enum uncore_index index)) { mutex_lock(&uncore_lock); - uncore_read = read_control_freq; - uncore_write = write_control_freq; - uncore_read_freq = read_freq; + uncore_read = read; + uncore_write = write; if (!uncore_root_kobj) uncore_root_kobj = kobject_create_and_add("intel_uncore_frequency", diff --git a/drivers/platform/x86/intel-uncore-frequency-common.h b/drivers/platform/x86/intel-uncore-frequency-common.h index 2d98931cd8e2..4c245b945e4e 100644 --- a/drivers/platform/x86/intel-uncore-frequency-common.h +++ b/drivers/platform/x86/intel-uncore-frequency-common.h @@ -69,13 +69,13 @@ struct uncore_data { enum uncore_index { UNCORE_INDEX_MIN_FREQ, UNCORE_INDEX_MAX_FREQ, + UNCORE_INDEX_CURRENT_FREQ, }; -int uncore_freq_common_init(int (*read_control_freq)(struct uncore_data *data, unsigned int *value, - enum uncore_index index), - int (*write_control_freq)(struct uncore_data *data, unsigned int input, - enum uncore_index index), - int (*uncore_read_freq)(struct uncore_data *data, unsigned int *freq)); +int uncore_freq_common_init(int (*read)(struct uncore_data *data, unsigned int *value, + enum uncore_index index), + int (*write)(struct uncore_data *data, unsigned int input, + enum uncore_index index)); void uncore_freq_common_exit(void); int uncore_freq_add_entry(struct uncore_data *data, int cpu); void uncore_freq_remove_die_entry(struct uncore_data *data); diff --git a/drivers/platform/x86/intel-uncore-frequency-tpmi.c b/drivers/platform/x86/intel-uncore-frequency-tpmi.c index 77425a226687..36919b4620b9 100644 --- a/drivers/platform/x86/intel-uncore-frequency-tpmi.c +++ b/drivers/platform/x86/intel-uncore-frequency-tpmi.c @@ -91,7 +91,7 @@ static void read_control_freq(struct tpmi_uncore_cluster_info *cluster_info, #define UNCORE_MAX_RATIO FIELD_MAX(UNCORE_MAX_RATIO_MASK) -/* Callback for sysfs read for max/min frequencies. Called under mutex locks */ +/* Helper for sysfs read for max/min frequencies. Called under mutex locks */ static int uncore_read_control_freq(struct uncore_data *data, unsigned int *value, enum uncore_index index) { @@ -207,7 +207,7 @@ static int uncore_write_control_freq(struct uncore_data *data, unsigned int inpu return 0; } -/* Callback for sysfs read for the current uncore frequency. Called under mutex locks */ +/* Helper for sysfs read for the current uncore frequency. Called under mutex locks */ static int uncore_read_freq(struct uncore_data *data, unsigned int *freq) { struct tpmi_uncore_cluster_info *cluster_info; @@ -223,6 +223,24 @@ static int uncore_read_freq(struct uncore_data *data, unsigned int *freq) return 0; } +/* Callback for sysfs read for TPMI uncore values. Called under mutex locks. */ +static int uncore_read(struct uncore_data *data, unsigned int *value, enum uncore_index index) +{ + switch (index) { + case UNCORE_INDEX_MIN_FREQ: + case UNCORE_INDEX_MAX_FREQ: + return uncore_read_control_freq(data, value, index); + + case UNCORE_INDEX_CURRENT_FREQ: + return uncore_read_freq(data, value); + + default: + break; + } + + return -EOPNOTSUPP; +} + static void remove_cluster_entries(struct tpmi_uncore_struct *tpmi_uncore) { int i; @@ -273,8 +291,7 @@ static int uncore_probe(struct auxiliary_device *auxdev, const struct auxiliary_ return -EINVAL; /* Register callbacks to uncore core */ - ret = uncore_freq_common_init(uncore_read_control_freq, uncore_write_control_freq, - uncore_read_freq); + ret = uncore_freq_common_init(uncore_read, uncore_write_control_freq); if (ret) return ret; diff --git a/drivers/platform/x86/intel-uncore-frequency.c b/drivers/platform/x86/intel-uncore-frequency.c index dd0e950c1d03..71607ac2e994 100644 --- a/drivers/platform/x86/intel-uncore-frequency.c +++ b/drivers/platform/x86/intel-uncore-frequency.c @@ -114,6 +114,23 @@ static int uncore_read_freq(struct uncore_data *data, unsigned int *freq) return 0; } +static int uncore_read(struct uncore_data *data, unsigned int *value, enum uncore_index index) +{ + switch (index) { + case UNCORE_INDEX_MIN_FREQ: + case UNCORE_INDEX_MAX_FREQ: + return uncore_read_control_freq(data, value, index); + + case UNCORE_INDEX_CURRENT_FREQ: + return uncore_read_freq(data, value); + + default: + break; + } + + return -EOPNOTSUPP; +} + /* Caller provides protection */ static struct uncore_data *uncore_get_instance(unsigned int cpu) { @@ -236,8 +253,7 @@ static int __init intel_uncore_init(void) if (!uncore_instances) return -ENOMEM; - ret = uncore_freq_common_init(uncore_read_control_freq, uncore_write_control_freq, - uncore_read_freq); + ret = uncore_freq_common_init(uncore_read, uncore_write_control_freq); if (ret) goto err_free; -- Gitee From ff596f1539f94d8de7c7d89f28e76a10d973b8d6 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Mon, 17 Jun 2024 09:04:39 +0300 Subject: [PATCH 06/10] platform/x86/intel-uncore-freq: Rename the sysfs helper macro names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ANBZ: #21537 commit b2cc9f908af19dd851dd4642325daf0e86614885 upstream. The macros to create sysfs entries are going to be used for other attributes in addition to current min/max frequencies only, so rename these to be more generic. No functional change intended. Intel-SIG: commit b2cc9f908af1 platform/x86/intel-uncore-freq: Rename the sysfs helper macro names. Backport intel uncore-freq driver update from 6.11 Signed-off-by: Tero Kristo Acked-by: Srinivas Pandruvada Link: https://lore.kernel.org/r/20240617060708.892981-7-tero.kristo@linux.intel.com Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen [ Yingbao Jia: amend commit log ] Signed-off-by: Yingbao Jia --- .../x86/intel-uncore-frequency-common.c | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/drivers/platform/x86/intel-uncore-frequency-common.c b/drivers/platform/x86/intel-uncore-frequency-common.c index 86e3758820fc..7fb81b63dffe 100644 --- a/drivers/platform/x86/intel-uncore-frequency-common.c +++ b/drivers/platform/x86/intel-uncore-frequency-common.c @@ -43,8 +43,7 @@ static ssize_t show_package_id(struct kobject *kobj, struct kobj_attribute *attr return sprintf(buf, "%u\n", data->package_id); } -static ssize_t show_min_max_freq_khz(struct uncore_data *data, - char *buf, enum uncore_index index) +static ssize_t show_attr(struct uncore_data *data, char *buf, enum uncore_index index) { unsigned int value; int ret; @@ -58,9 +57,8 @@ static ssize_t show_min_max_freq_khz(struct uncore_data *data, return sprintf(buf, "%u\n", value); } -static ssize_t store_min_max_freq_khz(struct uncore_data *data, - const char *buf, ssize_t count, - enum uncore_index index) +static ssize_t store_attr(struct uncore_data *data, const char *buf, ssize_t count, + enum uncore_index index) { unsigned int input; int ret; @@ -92,24 +90,23 @@ static ssize_t show_perf_status_freq_khz(struct uncore_data *data, char *buf) return sprintf(buf, "%u\n", freq); } -#define store_uncore_min_max(name, min_max) \ +#define store_uncore_attr(name, index) \ static ssize_t store_##name(struct kobject *kobj, \ struct kobj_attribute *attr, \ const char *buf, size_t count) \ { \ struct uncore_data *data = container_of(attr, struct uncore_data, name##_kobj_attr);\ \ - return store_min_max_freq_khz(data, buf, count, \ - min_max); \ + return store_attr(data, buf, count, index); \ } -#define show_uncore_min_max(name, min_max) \ +#define show_uncore_attr(name, index) \ static ssize_t show_##name(struct kobject *kobj, \ struct kobj_attribute *attr, char *buf)\ { \ struct uncore_data *data = container_of(attr, struct uncore_data, name##_kobj_attr);\ \ - return show_min_max_freq_khz(data, buf, min_max); \ + return show_attr(data, buf, index); \ } #define show_uncore_perf_status(name) \ @@ -121,11 +118,11 @@ static ssize_t show_perf_status_freq_khz(struct uncore_data *data, char *buf) return show_perf_status_freq_khz(data, buf); \ } -store_uncore_min_max(min_freq_khz, UNCORE_INDEX_MIN_FREQ); -store_uncore_min_max(max_freq_khz, UNCORE_INDEX_MAX_FREQ); +store_uncore_attr(min_freq_khz, UNCORE_INDEX_MIN_FREQ); +store_uncore_attr(max_freq_khz, UNCORE_INDEX_MAX_FREQ); -show_uncore_min_max(min_freq_khz, UNCORE_INDEX_MIN_FREQ); -show_uncore_min_max(max_freq_khz, UNCORE_INDEX_MAX_FREQ); +show_uncore_attr(min_freq_khz, UNCORE_INDEX_MIN_FREQ); +show_uncore_attr(max_freq_khz, UNCORE_INDEX_MAX_FREQ); show_uncore_perf_status(current_freq_khz); -- Gitee From a1166b45419b9e4b6860d9bfa3ed54f2670b4d47 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Mon, 17 Jun 2024 09:04:40 +0300 Subject: [PATCH 07/10] platform/x86/intel-uncore-freq: Use generic helpers for current frequency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ANBZ: #21537 commit 7b3ffe0d815d15310545f77d444ada92c5d26903 upstream. Use the generic sysfs helpers for reading the current frequency also, and remove the custom ones. No functional change intended. Intel-SIG: commit 7b3ffe0d815d platform/x86/intel-uncore-freq: Use generic helpers for current frequency. Backport intel uncore-freq driver update from 6.11 Signed-off-by: Tero Kristo Acked-by: Srinivas Pandruvada Link: https://lore.kernel.org/r/20240617060708.892981-8-tero.kristo@linux.intel.com Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen [ Yingbao Jia: amend commit log ] Signed-off-by: Yingbao Jia --- .../x86/intel-uncore-frequency-common.c | 25 +------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/drivers/platform/x86/intel-uncore-frequency-common.c b/drivers/platform/x86/intel-uncore-frequency-common.c index 7fb81b63dffe..030f332ffd46 100644 --- a/drivers/platform/x86/intel-uncore-frequency-common.c +++ b/drivers/platform/x86/intel-uncore-frequency-common.c @@ -76,20 +76,6 @@ static ssize_t store_attr(struct uncore_data *data, const char *buf, ssize_t cou return count; } -static ssize_t show_perf_status_freq_khz(struct uncore_data *data, char *buf) -{ - unsigned int freq; - int ret; - - mutex_lock(&uncore_lock); - ret = uncore_read(data, &freq, UNCORE_INDEX_CURRENT_FREQ); - mutex_unlock(&uncore_lock); - if (ret) - return ret; - - return sprintf(buf, "%u\n", freq); -} - #define store_uncore_attr(name, index) \ static ssize_t store_##name(struct kobject *kobj, \ struct kobj_attribute *attr, \ @@ -109,22 +95,13 @@ static ssize_t show_perf_status_freq_khz(struct uncore_data *data, char *buf) return show_attr(data, buf, index); \ } -#define show_uncore_perf_status(name) \ - static ssize_t show_##name(struct kobject *kobj, \ - struct kobj_attribute *attr, char *buf)\ - { \ - struct uncore_data *data = container_of(attr, struct uncore_data, name##_kobj_attr);\ - \ - return show_perf_status_freq_khz(data, buf); \ - } - store_uncore_attr(min_freq_khz, UNCORE_INDEX_MIN_FREQ); store_uncore_attr(max_freq_khz, UNCORE_INDEX_MAX_FREQ); show_uncore_attr(min_freq_khz, UNCORE_INDEX_MIN_FREQ); show_uncore_attr(max_freq_khz, UNCORE_INDEX_MAX_FREQ); -show_uncore_perf_status(current_freq_khz); +show_uncore_attr(current_freq_khz, UNCORE_INDEX_CURRENT_FREQ); #define show_uncore_data(member_name) \ static ssize_t show_##member_name(struct kobject *kobj, \ -- Gitee From 0b3a882e9f724b4b20262040082968a8c02ce4bb Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Tue, 20 Aug 2024 13:45:58 -0700 Subject: [PATCH 08/10] platform/x86/intel-uncore-freq: Do not present separate package-die domain MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ANBZ: #21537 commit bb9a9bf2787fbe1a4e003daabc8f7a31c17740d6 upstream. The scope of uncore control is per power domain with TPMI. There are two types of processor topologies can be presented by CPUID extended topology leaf irrespective of the hardware architecture: 1. A die is not enumerated in CPUID. In this case there is only one die in a package is visible. In this case there can be multiple power domains in a single die. 2. A power domain in a package is enumerated as a die in CPUID. So there is one power domain per die. To allow die level controls, the current implementation creates a root domain and aggregates all information from power domains in it. This is well suited for configuration 1 above. But for configuration 2 above, the root domain will present the same information as present by power domain. So, no use of aggregating. To check the configuration, call topology_max_dies_per_package(). If it is more than one, avoid creating root domain. Intel-SIG: commit bb9a9bf2787f platform/x86/intel-uncore-freq: Do not present separate package-die domain. Backport Intel uncore-freq driver elc support and update Signed-off-by: Srinivas Pandruvada Reviewed-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20240820204558.1296319-1-srinivas.pandruvada@linux.intel.com Reviewed-by: Hans de Goede Signed-off-by: Hans de Goede [ Yingbao Jia: amend commit log ] Signed-off-by: Yingbao Jia --- drivers/platform/x86/intel-uncore-frequency-tpmi.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/platform/x86/intel-uncore-frequency-tpmi.c b/drivers/platform/x86/intel-uncore-frequency-tpmi.c index 36919b4620b9..7ac355306646 100644 --- a/drivers/platform/x86/intel-uncore-frequency-tpmi.c +++ b/drivers/platform/x86/intel-uncore-frequency-tpmi.c @@ -427,6 +427,9 @@ static int uncore_probe(struct auxiliary_device *auxdev, const struct auxiliary_ auxiliary_set_drvdata(auxdev, tpmi_uncore); + if (topology_max_die_per_package() > 1) + return 0; + tpmi_uncore->root_cluster.root_domain = true; tpmi_uncore->root_cluster.uncore_root = tpmi_uncore; @@ -450,7 +453,9 @@ static void uncore_remove(struct auxiliary_device *auxdev) { struct tpmi_uncore_struct *tpmi_uncore = auxiliary_get_drvdata(auxdev); - uncore_freq_remove_die_entry(&tpmi_uncore->root_cluster.uncore_data); + if (tpmi_uncore->root_cluster.root_domain) + uncore_freq_remove_die_entry(&tpmi_uncore->root_cluster.uncore_data); + remove_cluster_entries(tpmi_uncore); uncore_freq_common_exit(); -- Gitee From d3a8ad39f9735019454fa55bc968e20a0175202f Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Wed, 28 Aug 2024 18:34:54 +0300 Subject: [PATCH 09/10] platform/x86/intel-uncore-freq: Add support for efficiency latency control MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ANBZ: #21537 commit bb516dc79c4a6334d5ef6bdbd0d262cf8be9db8e upstream. Add efficiency latency control support to the TPMI uncore driver. This defines two new threshold values for controlling uncore frequency, low threshold and high threshold. When CPU utilization is below low threshold, the user configurable floor latency control frequency can be used by the system. When CPU utilization is above high threshold, the uncore frequency is increased in 100MHz steps until power limit is reached. Intel-SIG: commit bb516dc79c4a platform/x86/intel-uncore-freq: Add support for efficiency latency control. Backport Intel uncore-freq driver elc support and update Signed-off-by: Tero Kristo Reviewed-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20240828153657.1296410-3-tero.kristo@linux.intel.com Signed-off-by: Hans de Goede [ Yingbao Jia: amend commit log ] Signed-off-by: Yingbao Jia --- .../x86/intel-uncore-frequency-common.h | 4 + .../x86/intel-uncore-frequency-tpmi.c | 158 +++++++++++++++++- 2 files changed, 160 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/intel-uncore-frequency-common.h b/drivers/platform/x86/intel-uncore-frequency-common.h index 4c245b945e4e..b5c7311bfa05 100644 --- a/drivers/platform/x86/intel-uncore-frequency-common.h +++ b/drivers/platform/x86/intel-uncore-frequency-common.h @@ -70,6 +70,10 @@ enum uncore_index { UNCORE_INDEX_MIN_FREQ, UNCORE_INDEX_MAX_FREQ, UNCORE_INDEX_CURRENT_FREQ, + UNCORE_INDEX_EFF_LAT_CTRL_LOW_THRESHOLD, + UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD, + UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE, + UNCORE_INDEX_EFF_LAT_CTRL_FREQ, }; int uncore_freq_common_init(int (*read)(struct uncore_data *data, unsigned int *value, diff --git a/drivers/platform/x86/intel-uncore-frequency-tpmi.c b/drivers/platform/x86/intel-uncore-frequency-tpmi.c index 7ac355306646..72d3623f6717 100644 --- a/drivers/platform/x86/intel-uncore-frequency-tpmi.c +++ b/drivers/platform/x86/intel-uncore-frequency-tpmi.c @@ -30,6 +30,7 @@ #define UNCORE_MAJOR_VERSION 0 #define UNCORE_MINOR_VERSION 2 +#define UNCORE_ELC_SUPPORTED_VERSION 2 #define UNCORE_HEADER_INDEX 0 #define UNCORE_FABRIC_CLUSTER_OFFSET 8 @@ -46,6 +47,7 @@ struct tpmi_uncore_struct; /* Information for each cluster */ struct tpmi_uncore_cluster_info { bool root_domain; + bool elc_supported; u8 __iomem *cluster_base; struct uncore_data uncore_data; struct tpmi_uncore_struct *uncore_root; @@ -75,6 +77,10 @@ struct tpmi_uncore_struct { /* Bit definitions for CONTROL register */ #define UNCORE_MAX_RATIO_MASK GENMASK_ULL(14, 8) #define UNCORE_MIN_RATIO_MASK GENMASK_ULL(21, 15) +#define UNCORE_EFF_LAT_CTRL_RATIO_MASK GENMASK_ULL(28, 22) +#define UNCORE_EFF_LAT_CTRL_LOW_THRESHOLD_MASK GENMASK_ULL(38, 32) +#define UNCORE_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE BIT(39) +#define UNCORE_EFF_LAT_CTRL_HIGH_THRESHOLD_MASK GENMASK_ULL(46, 40) /* Helper function to read MMIO offset for max/min control frequency */ static void read_control_freq(struct tpmi_uncore_cluster_info *cluster_info, @@ -89,6 +95,48 @@ static void read_control_freq(struct tpmi_uncore_cluster_info *cluster_info, *value = FIELD_GET(UNCORE_MIN_RATIO_MASK, control) * UNCORE_FREQ_KHZ_MULTIPLIER; } +/* Helper function to read efficiency latency control values over MMIO */ +static int read_eff_lat_ctrl(struct uncore_data *data, unsigned int *val, enum uncore_index index) +{ + struct tpmi_uncore_cluster_info *cluster_info; + u64 ctrl; + + cluster_info = container_of(data, struct tpmi_uncore_cluster_info, uncore_data); + if (cluster_info->root_domain) + return -ENODATA; + + if (!cluster_info->elc_supported) + return -EOPNOTSUPP; + + ctrl = readq(cluster_info->cluster_base + UNCORE_CONTROL_INDEX); + + switch (index) { + case UNCORE_INDEX_EFF_LAT_CTRL_LOW_THRESHOLD: + *val = FIELD_GET(UNCORE_EFF_LAT_CTRL_LOW_THRESHOLD_MASK, ctrl); + *val *= 100; + *val = DIV_ROUND_UP(*val, FIELD_MAX(UNCORE_EFF_LAT_CTRL_LOW_THRESHOLD_MASK)); + break; + + case UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD: + *val = FIELD_GET(UNCORE_EFF_LAT_CTRL_HIGH_THRESHOLD_MASK, ctrl); + *val *= 100; + *val = DIV_ROUND_UP(*val, FIELD_MAX(UNCORE_EFF_LAT_CTRL_HIGH_THRESHOLD_MASK)); + break; + + case UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE: + *val = FIELD_GET(UNCORE_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE, ctrl); + break; + case UNCORE_INDEX_EFF_LAT_CTRL_FREQ: + *val = FIELD_GET(UNCORE_EFF_LAT_CTRL_RATIO_MASK, ctrl) * UNCORE_FREQ_KHZ_MULTIPLIER; + break; + + default: + return -EOPNOTSUPP; + } + + return 0; +} + #define UNCORE_MAX_RATIO FIELD_MAX(UNCORE_MAX_RATIO_MASK) /* Helper for sysfs read for max/min frequencies. Called under mutex locks */ @@ -137,6 +185,82 @@ static int uncore_read_control_freq(struct uncore_data *data, unsigned int *valu return 0; } +/* Helper function for writing efficiency latency control values over MMIO */ +static int write_eff_lat_ctrl(struct uncore_data *data, unsigned int val, enum uncore_index index) +{ + struct tpmi_uncore_cluster_info *cluster_info; + u64 control; + + cluster_info = container_of(data, struct tpmi_uncore_cluster_info, uncore_data); + + if (cluster_info->root_domain) + return -ENODATA; + + if (!cluster_info->elc_supported) + return -EOPNOTSUPP; + + switch (index) { + case UNCORE_INDEX_EFF_LAT_CTRL_LOW_THRESHOLD: + if (val > 100) + return -EINVAL; + break; + + case UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD: + if (val > 100) + return -EINVAL; + break; + + case UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE: + if (val > 1) + return -EINVAL; + break; + + case UNCORE_INDEX_EFF_LAT_CTRL_FREQ: + val /= UNCORE_FREQ_KHZ_MULTIPLIER; + if (val > FIELD_MAX(UNCORE_EFF_LAT_CTRL_RATIO_MASK)) + return -EINVAL; + break; + + default: + return -EOPNOTSUPP; + } + + control = readq(cluster_info->cluster_base + UNCORE_CONTROL_INDEX); + + switch (index) { + case UNCORE_INDEX_EFF_LAT_CTRL_LOW_THRESHOLD: + val *= FIELD_MAX(UNCORE_EFF_LAT_CTRL_LOW_THRESHOLD_MASK); + val /= 100; + control &= ~UNCORE_EFF_LAT_CTRL_LOW_THRESHOLD_MASK; + control |= FIELD_PREP(UNCORE_EFF_LAT_CTRL_LOW_THRESHOLD_MASK, val); + break; + + case UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD: + val *= FIELD_MAX(UNCORE_EFF_LAT_CTRL_HIGH_THRESHOLD_MASK); + val /= 100; + control &= ~UNCORE_EFF_LAT_CTRL_HIGH_THRESHOLD_MASK; + control |= FIELD_PREP(UNCORE_EFF_LAT_CTRL_HIGH_THRESHOLD_MASK, val); + break; + + case UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE: + control &= ~UNCORE_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE; + control |= FIELD_PREP(UNCORE_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE, val); + break; + + case UNCORE_INDEX_EFF_LAT_CTRL_FREQ: + control &= ~UNCORE_EFF_LAT_CTRL_RATIO_MASK; + control |= FIELD_PREP(UNCORE_EFF_LAT_CTRL_RATIO_MASK, val); + break; + + default: + break; + } + + writeq(control, cluster_info->cluster_base + UNCORE_CONTROL_INDEX); + + return 0; +} + /* Helper function to write MMIO offset for max/min control frequency */ static void write_control_freq(struct tpmi_uncore_cluster_info *cluster_info, unsigned int input, unsigned int index) @@ -156,7 +280,7 @@ static void write_control_freq(struct tpmi_uncore_cluster_info *cluster_info, un writeq(control, (cluster_info->cluster_base + UNCORE_CONTROL_INDEX)); } -/* Callback for sysfs write for max/min frequencies. Called under mutex locks */ +/* Helper for sysfs write for max/min frequencies. Called under mutex locks */ static int uncore_write_control_freq(struct uncore_data *data, unsigned int input, enum uncore_index index) { @@ -234,6 +358,33 @@ static int uncore_read(struct uncore_data *data, unsigned int *value, enum uncor case UNCORE_INDEX_CURRENT_FREQ: return uncore_read_freq(data, value); + case UNCORE_INDEX_EFF_LAT_CTRL_LOW_THRESHOLD: + case UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD: + case UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE: + case UNCORE_INDEX_EFF_LAT_CTRL_FREQ: + return read_eff_lat_ctrl(data, value, index); + + default: + break; + } + + return -EOPNOTSUPP; +} + +/* Callback for sysfs write for TPMI uncore data. Called under mutex locks. */ +static int uncore_write(struct uncore_data *data, unsigned int value, enum uncore_index index) +{ + switch (index) { + case UNCORE_INDEX_EFF_LAT_CTRL_LOW_THRESHOLD: + case UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD: + case UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE: + case UNCORE_INDEX_EFF_LAT_CTRL_FREQ: + return write_eff_lat_ctrl(data, value, index); + + case UNCORE_INDEX_MIN_FREQ: + case UNCORE_INDEX_MAX_FREQ: + return uncore_write_control_freq(data, value, index); + default: break; } @@ -291,7 +442,7 @@ static int uncore_probe(struct auxiliary_device *auxdev, const struct auxiliary_ return -EINVAL; /* Register callbacks to uncore core */ - ret = uncore_freq_common_init(uncore_read, uncore_write_control_freq); + ret = uncore_freq_common_init(uncore_read, uncore_write); if (ret) return ret; @@ -409,6 +560,9 @@ static int uncore_probe(struct auxiliary_device *auxdev, const struct auxiliary_ cluster_info->uncore_root = tpmi_uncore; + if (TPMI_MINOR_VERSION(pd_info->ufs_header_ver) >= UNCORE_ELC_SUPPORTED_VERSION) + cluster_info->elc_supported = true; + ret = uncore_freq_add_entry(&cluster_info->uncore_data, 0); if (ret) { cluster_info->cluster_base = NULL; -- Gitee From 691430c1e9ad6cb72ba280474377855ffbb3dd0c Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Wed, 28 Aug 2024 18:34:55 +0300 Subject: [PATCH 10/10] platform/x86/intel-uncore-freq: Add efficiency latency control to sysfs interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ANBZ: #21537 commit 24b6616355f7eb2a839776578b104a0348b4f77f upstream. Add the TPMI efficiency latency control fields to the sysfs interface. The sysfs files are mapped to the TPMI uncore driver via the registered uncore_read and uncore_write driver callbacks. These fields are not populated on older non TPMI hardware. Intel-SIG: commit 24b6616355f7 platform/x86/intel-uncore-freq: Add efficiency latency control to sysfs interface. Backport Intel uncore-freq driver elc support and update Signed-off-by: Tero Kristo Reviewed-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20240828153657.1296410-4-tero.kristo@linux.intel.com Signed-off-by: Hans de Goede [ Yingbao Jia: amend commit log ] Signed-off-by: Yingbao Jia --- .../x86/intel-uncore-frequency-common.c | 42 ++++++++++++++++--- .../x86/intel-uncore-frequency-common.h | 13 +++++- 2 files changed, 49 insertions(+), 6 deletions(-) diff --git a/drivers/platform/x86/intel-uncore-frequency-common.c b/drivers/platform/x86/intel-uncore-frequency-common.c index 030f332ffd46..638d8bea1525 100644 --- a/drivers/platform/x86/intel-uncore-frequency-common.c +++ b/drivers/platform/x86/intel-uncore-frequency-common.c @@ -60,11 +60,16 @@ static ssize_t show_attr(struct uncore_data *data, char *buf, enum uncore_index static ssize_t store_attr(struct uncore_data *data, const char *buf, ssize_t count, enum uncore_index index) { - unsigned int input; + unsigned int input = 0; int ret; - if (kstrtouint(buf, 10, &input)) - return -EINVAL; + if (index == UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE) { + if (kstrtobool(buf, (bool *)&input)) + return -EINVAL; + } else { + if (kstrtouint(buf, 10, &input)) + return -EINVAL; + } mutex_lock(&uncore_lock); ret = uncore_write(data, input, index); @@ -103,6 +108,18 @@ show_uncore_attr(max_freq_khz, UNCORE_INDEX_MAX_FREQ); show_uncore_attr(current_freq_khz, UNCORE_INDEX_CURRENT_FREQ); +store_uncore_attr(elc_low_threshold_percent, UNCORE_INDEX_EFF_LAT_CTRL_LOW_THRESHOLD); +store_uncore_attr(elc_high_threshold_percent, UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD); +store_uncore_attr(elc_high_threshold_enable, + UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE); +store_uncore_attr(elc_floor_freq_khz, UNCORE_INDEX_EFF_LAT_CTRL_FREQ); + +show_uncore_attr(elc_low_threshold_percent, UNCORE_INDEX_EFF_LAT_CTRL_LOW_THRESHOLD); +show_uncore_attr(elc_high_threshold_percent, UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD); +show_uncore_attr(elc_high_threshold_enable, + UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE); +show_uncore_attr(elc_floor_freq_khz, UNCORE_INDEX_EFF_LAT_CTRL_FREQ); + #define show_uncore_data(member_name) \ static ssize_t show_##member_name(struct kobject *kobj, \ struct kobj_attribute *attr, char *buf)\ @@ -146,7 +163,8 @@ show_uncore_data(initial_max_freq_khz); static int create_attr_group(struct uncore_data *data, char *name) { - int ret, freq, index = 0; + int ret, index = 0; + unsigned int val; init_attribute_rw(max_freq_khz); init_attribute_rw(min_freq_khz); @@ -168,10 +186,24 @@ static int create_attr_group(struct uncore_data *data, char *name) data->uncore_attrs[index++] = &data->initial_min_freq_khz_kobj_attr.attr; data->uncore_attrs[index++] = &data->initial_max_freq_khz_kobj_attr.attr; - ret = uncore_read(data, &freq, UNCORE_INDEX_CURRENT_FREQ); + ret = uncore_read(data, &val, UNCORE_INDEX_CURRENT_FREQ); if (!ret) data->uncore_attrs[index++] = &data->current_freq_khz_kobj_attr.attr; + ret = uncore_read(data, &val, UNCORE_INDEX_EFF_LAT_CTRL_LOW_THRESHOLD); + if (!ret) { + init_attribute_rw(elc_low_threshold_percent); + init_attribute_rw(elc_high_threshold_percent); + init_attribute_rw(elc_high_threshold_enable); + init_attribute_rw(elc_floor_freq_khz); + + data->uncore_attrs[index++] = &data->elc_low_threshold_percent_kobj_attr.attr; + data->uncore_attrs[index++] = &data->elc_high_threshold_percent_kobj_attr.attr; + data->uncore_attrs[index++] = + &data->elc_high_threshold_enable_kobj_attr.attr; + data->uncore_attrs[index++] = &data->elc_floor_freq_khz_kobj_attr.attr; + } + data->uncore_attrs[index] = NULL; data->uncore_attr_group.name = name; diff --git a/drivers/platform/x86/intel-uncore-frequency-common.h b/drivers/platform/x86/intel-uncore-frequency-common.h index b5c7311bfa05..26c854cd5d97 100644 --- a/drivers/platform/x86/intel-uncore-frequency-common.h +++ b/drivers/platform/x86/intel-uncore-frequency-common.h @@ -34,6 +34,13 @@ * @domain_id_kobj_attr: Storage for kobject attribute domain_id * @fabric_cluster_id_kobj_attr: Storage for kobject attribute fabric_cluster_id * @package_id_kobj_attr: Storage for kobject attribute package_id + * @elc_low_threshold_percent_kobj_attr: + Storage for kobject attribute elc_low_threshold_percent + * @elc_high_threshold_percent_kobj_attr: + Storage for kobject attribute elc_high_threshold_percent + * @elc_high_threshold_enable_kobj_attr: + Storage for kobject attribute elc_high_threshold_enable + * @elc_floor_freq_khz_kobj_attr: Storage for kobject attribute elc_floor_freq_khz * @uncore_attrs: Attribute storage for group creation * * This structure is used to encapsulate all data related to uncore sysfs @@ -61,7 +68,11 @@ struct uncore_data { struct kobj_attribute domain_id_kobj_attr; struct kobj_attribute fabric_cluster_id_kobj_attr; struct kobj_attribute package_id_kobj_attr; - struct attribute *uncore_attrs[9]; + struct kobj_attribute elc_low_threshold_percent_kobj_attr; + struct kobj_attribute elc_high_threshold_percent_kobj_attr; + struct kobj_attribute elc_high_threshold_enable_kobj_attr; + struct kobj_attribute elc_floor_freq_khz_kobj_attr; + struct attribute *uncore_attrs[13]; }; #define UNCORE_DOMAIN_ID_INVALID -1 -- Gitee