Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

platform/x86/intel-uncore-freq: Split common and enumeration part

Split the current driver in two parts:
- Common part: All the commom function other than enumeration function.
- Enumeration/HW specific part: The current enumeration using CPU model
is left in the old module. This uses service of common driver to register
sysfs objects. Also provide callbacks for MSR access related to uncore.
- Add MODULE_DEVICE_TABLE to uncore-frequency.c

No functional changes are expected.

Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@intel.com>
Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Link: https://lore.kernel.org/r/20220204000306.2517447-5-srinivas.pandruvada@linux.intel.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>

authored by

Srinivas Pandruvada and committed by
Hans de Goede
dbce412a 414eef27

+365 -283
+2
drivers/platform/x86/intel/uncore-frequency/Makefile
··· 5 5 6 6 obj-$(CONFIG_INTEL_UNCORE_FREQ_CONTROL) += intel-uncore-frequency.o 7 7 intel-uncore-frequency-y := uncore-frequency.o 8 + obj-$(CONFIG_INTEL_UNCORE_FREQ_CONTROL) += intel-uncore-frequency-common.o 9 + intel-uncore-frequency-common-y := uncore-frequency-common.o
+252
drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Intel Uncore Frequency Control: Common code implementation 4 + * Copyright (c) 2022, Intel Corporation. 5 + * All rights reserved. 6 + * 7 + */ 8 + #include <linux/cpu.h> 9 + #include <linux/module.h> 10 + #include "uncore-frequency-common.h" 11 + 12 + /* Mutex to control all mutual exclusions */ 13 + static DEFINE_MUTEX(uncore_lock); 14 + /* Root of the all uncore sysfs kobjs */ 15 + static struct kobject *uncore_root_kobj; 16 + /* uncore instance count */ 17 + static int uncore_instance_count; 18 + 19 + /* callbacks for actual HW read/write */ 20 + static int (*uncore_read)(struct uncore_data *data, unsigned int *min, unsigned int *max); 21 + static int (*uncore_write)(struct uncore_data *data, unsigned int input, unsigned int min_max); 22 + static int (*uncore_read_freq)(struct uncore_data *data, unsigned int *freq); 23 + 24 + static ssize_t show_min_max_freq_khz(struct uncore_data *data, 25 + char *buf, int min_max) 26 + { 27 + unsigned int min, max; 28 + int ret; 29 + 30 + mutex_lock(&uncore_lock); 31 + ret = uncore_read(data, &min, &max); 32 + mutex_unlock(&uncore_lock); 33 + if (ret) 34 + return ret; 35 + 36 + if (min_max) 37 + return sprintf(buf, "%u\n", max); 38 + 39 + return sprintf(buf, "%u\n", min); 40 + } 41 + 42 + static ssize_t store_min_max_freq_khz(struct uncore_data *data, 43 + const char *buf, ssize_t count, 44 + int min_max) 45 + { 46 + unsigned int input; 47 + 48 + if (kstrtouint(buf, 10, &input)) 49 + return -EINVAL; 50 + 51 + mutex_lock(&uncore_lock); 52 + uncore_write(data, input, min_max); 53 + mutex_unlock(&uncore_lock); 54 + 55 + return count; 56 + } 57 + 58 + static ssize_t show_perf_status_freq_khz(struct uncore_data *data, char *buf) 59 + { 60 + unsigned int freq; 61 + int ret; 62 + 63 + mutex_lock(&uncore_lock); 64 + ret = uncore_read_freq(data, &freq); 65 + mutex_unlock(&uncore_lock); 66 + if (ret) 67 + return ret; 68 + 69 + return sprintf(buf, "%u\n", freq); 70 + } 71 + 72 + #define store_uncore_min_max(name, min_max) \ 73 + static ssize_t store_##name(struct device *dev, \ 74 + struct device_attribute *attr, \ 75 + const char *buf, size_t count) \ 76 + { \ 77 + struct uncore_data *data = container_of(attr, struct uncore_data, name##_dev_attr);\ 78 + \ 79 + return store_min_max_freq_khz(data, buf, count, \ 80 + min_max); \ 81 + } 82 + 83 + #define show_uncore_min_max(name, min_max) \ 84 + static ssize_t show_##name(struct device *dev, \ 85 + struct device_attribute *attr, char *buf)\ 86 + { \ 87 + struct uncore_data *data = container_of(attr, struct uncore_data, name##_dev_attr);\ 88 + \ 89 + return show_min_max_freq_khz(data, buf, min_max); \ 90 + } 91 + 92 + #define show_uncore_perf_status(name) \ 93 + static ssize_t show_##name(struct device *dev, \ 94 + struct device_attribute *attr, char *buf)\ 95 + { \ 96 + struct uncore_data *data = container_of(attr, struct uncore_data, name##_dev_attr);\ 97 + \ 98 + return show_perf_status_freq_khz(data, buf); \ 99 + } 100 + 101 + store_uncore_min_max(min_freq_khz, 0); 102 + store_uncore_min_max(max_freq_khz, 1); 103 + 104 + show_uncore_min_max(min_freq_khz, 0); 105 + show_uncore_min_max(max_freq_khz, 1); 106 + 107 + show_uncore_perf_status(current_freq_khz); 108 + 109 + #define show_uncore_data(member_name) \ 110 + static ssize_t show_##member_name(struct device *dev, \ 111 + struct device_attribute *attr, char *buf)\ 112 + { \ 113 + struct uncore_data *data = container_of(attr, struct uncore_data,\ 114 + member_name##_dev_attr);\ 115 + \ 116 + return scnprintf(buf, PAGE_SIZE, "%u\n", \ 117 + data->member_name); \ 118 + } \ 119 + 120 + show_uncore_data(initial_min_freq_khz); 121 + show_uncore_data(initial_max_freq_khz); 122 + 123 + #define init_attribute_rw(_name) \ 124 + do { \ 125 + sysfs_attr_init(&data->_name##_dev_attr.attr); \ 126 + data->_name##_dev_attr.show = show_##_name; \ 127 + data->_name##_dev_attr.store = store_##_name; \ 128 + data->_name##_dev_attr.attr.name = #_name; \ 129 + data->_name##_dev_attr.attr.mode = 0644; \ 130 + } while (0) 131 + 132 + #define init_attribute_ro(_name) \ 133 + do { \ 134 + sysfs_attr_init(&data->_name##_dev_attr.attr); \ 135 + data->_name##_dev_attr.show = show_##_name; \ 136 + data->_name##_dev_attr.store = NULL; \ 137 + data->_name##_dev_attr.attr.name = #_name; \ 138 + data->_name##_dev_attr.attr.mode = 0444; \ 139 + } while (0) 140 + 141 + #define init_attribute_root_ro(_name) \ 142 + do { \ 143 + sysfs_attr_init(&data->_name##_dev_attr.attr); \ 144 + data->_name##_dev_attr.show = show_##_name; \ 145 + data->_name##_dev_attr.store = NULL; \ 146 + data->_name##_dev_attr.attr.name = #_name; \ 147 + data->_name##_dev_attr.attr.mode = 0400; \ 148 + } while (0) 149 + 150 + static int create_attr_group(struct uncore_data *data, char *name) 151 + { 152 + int ret, index = 0; 153 + 154 + init_attribute_rw(max_freq_khz); 155 + init_attribute_rw(min_freq_khz); 156 + init_attribute_ro(initial_min_freq_khz); 157 + init_attribute_ro(initial_max_freq_khz); 158 + init_attribute_root_ro(current_freq_khz); 159 + 160 + data->uncore_attrs[index++] = &data->max_freq_khz_dev_attr.attr; 161 + data->uncore_attrs[index++] = &data->min_freq_khz_dev_attr.attr; 162 + data->uncore_attrs[index++] = &data->initial_min_freq_khz_dev_attr.attr; 163 + data->uncore_attrs[index++] = &data->initial_max_freq_khz_dev_attr.attr; 164 + data->uncore_attrs[index++] = &data->current_freq_khz_dev_attr.attr; 165 + data->uncore_attrs[index] = NULL; 166 + 167 + data->uncore_attr_group.name = name; 168 + data->uncore_attr_group.attrs = data->uncore_attrs; 169 + ret = sysfs_create_group(uncore_root_kobj, &data->uncore_attr_group); 170 + 171 + return ret; 172 + } 173 + 174 + static void delete_attr_group(struct uncore_data *data, char *name) 175 + { 176 + sysfs_remove_group(uncore_root_kobj, &data->uncore_attr_group); 177 + } 178 + 179 + int uncore_freq_add_entry(struct uncore_data *data, int cpu) 180 + { 181 + int ret = 0; 182 + 183 + mutex_lock(&uncore_lock); 184 + if (data->valid) { 185 + /* control cpu changed */ 186 + data->control_cpu = cpu; 187 + goto uncore_unlock; 188 + } 189 + 190 + sprintf(data->name, "package_%02d_die_%02d", data->package_id, data->die_id); 191 + 192 + uncore_read(data, &data->initial_min_freq_khz, &data->initial_max_freq_khz); 193 + 194 + ret = create_attr_group(data, data->name); 195 + if (!ret) { 196 + data->control_cpu = cpu; 197 + data->valid = true; 198 + } 199 + 200 + uncore_unlock: 201 + mutex_unlock(&uncore_lock); 202 + 203 + return ret; 204 + } 205 + EXPORT_SYMBOL_NS_GPL(uncore_freq_add_entry, INTEL_UNCORE_FREQUENCY); 206 + 207 + void uncore_freq_remove_die_entry(struct uncore_data *data) 208 + { 209 + mutex_lock(&uncore_lock); 210 + delete_attr_group(data, data->name); 211 + data->control_cpu = -1; 212 + data->valid = false; 213 + mutex_unlock(&uncore_lock); 214 + } 215 + EXPORT_SYMBOL_NS_GPL(uncore_freq_remove_die_entry, INTEL_UNCORE_FREQUENCY); 216 + 217 + int uncore_freq_common_init(int (*read_control_freq)(struct uncore_data *data, unsigned int *min, unsigned int *max), 218 + int (*write_control_freq)(struct uncore_data *data, unsigned int input, unsigned int set_max), 219 + int (*read_freq)(struct uncore_data *data, unsigned int *freq)) 220 + { 221 + mutex_lock(&uncore_lock); 222 + 223 + uncore_read = read_control_freq; 224 + uncore_write = write_control_freq; 225 + uncore_read_freq = read_freq; 226 + 227 + if (!uncore_root_kobj) 228 + uncore_root_kobj = kobject_create_and_add("intel_uncore_frequency", 229 + &cpu_subsys.dev_root->kobj); 230 + if (uncore_root_kobj) 231 + ++uncore_instance_count; 232 + mutex_unlock(&uncore_lock); 233 + 234 + return (!!uncore_root_kobj); 235 + } 236 + EXPORT_SYMBOL_NS_GPL(uncore_freq_common_init, INTEL_UNCORE_FREQUENCY); 237 + 238 + void uncore_freq_common_exit(void) 239 + { 240 + mutex_lock(&uncore_lock); 241 + --uncore_instance_count; 242 + if (!uncore_instance_count) { 243 + kobject_put(uncore_root_kobj); 244 + uncore_root_kobj = NULL; 245 + } 246 + mutex_unlock(&uncore_lock); 247 + } 248 + EXPORT_SYMBOL_NS_GPL(uncore_freq_common_exit, INTEL_UNCORE_FREQUENCY); 249 + 250 + 251 + MODULE_LICENSE("GPL v2"); 252 + MODULE_DESCRIPTION("Intel Uncore Frequency Common Module");
+62
drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Intel Uncore Frequency Control: Common defines and prototypes 4 + * Copyright (c) 2022, Intel Corporation. 5 + * All rights reserved. 6 + * 7 + */ 8 + 9 + #ifndef __INTEL_UNCORE_FREQ_COMMON_H 10 + #define __INTEL_UNCORE_FREQ_COMMON_H 11 + 12 + #include <linux/device.h> 13 + 14 + /** 15 + * struct uncore_data - Encapsulate all uncore data 16 + * @stored_uncore_data: Last user changed MSR 620 value, which will be restored 17 + * on system resume. 18 + * @initial_min_freq_khz: Sampled minimum uncore frequency at driver init 19 + * @initial_max_freq_khz: Sampled maximum uncore frequency at driver init 20 + * @control_cpu: Designated CPU for a die to read/write 21 + * @valid: Mark the data valid/invalid 22 + * @package_id: Package id for this instance 23 + * @die_id: Die id for this instance 24 + * @name: Sysfs entry name for this instance 25 + * @uncore_attr_group: Attribute group storage 26 + * @max_freq_khz_dev_attr: Storage for device attribute max_freq_khz 27 + * @mix_freq_khz_dev_attr: Storage for device attribute min_freq_khz 28 + * @initial_max_freq_khz_dev_attr: Storage for device attribute initial_max_freq_khz 29 + * @initial_min_freq_khz_dev_attr: Storage for device attribute initial_min_freq_khz 30 + * @current_freq_khz_dev_attr: Storage for device attribute current_freq_khz 31 + * @uncore_attrs: Attribute storage for group creation 32 + * 33 + * This structure is used to encapsulate all data related to uncore sysfs 34 + * settings for a die/package. 35 + */ 36 + struct uncore_data { 37 + u64 stored_uncore_data; 38 + u32 initial_min_freq_khz; 39 + u32 initial_max_freq_khz; 40 + int control_cpu; 41 + bool valid; 42 + int package_id; 43 + int die_id; 44 + char name[32]; 45 + 46 + struct attribute_group uncore_attr_group; 47 + struct device_attribute max_freq_khz_dev_attr; 48 + struct device_attribute min_freq_khz_dev_attr; 49 + struct device_attribute initial_max_freq_khz_dev_attr; 50 + struct device_attribute initial_min_freq_khz_dev_attr; 51 + struct device_attribute current_freq_khz_dev_attr; 52 + struct attribute *uncore_attrs[6]; 53 + }; 54 + 55 + int uncore_freq_common_init(int (*read_control_freq)(struct uncore_data *data, unsigned int *min, unsigned int *max), 56 + int (*write_control_freq)(struct uncore_data *data, unsigned int input, unsigned int min_max), 57 + int (*uncore_read_freq)(struct uncore_data *data, unsigned int *freq)); 58 + void uncore_freq_common_exit(void); 59 + int uncore_freq_add_entry(struct uncore_data *data, int cpu); 60 + void uncore_freq_remove_die_entry(struct uncore_data *data); 61 + 62 + #endif
+49 -283
drivers/platform/x86/intel/uncore-frequency/uncore-frequency.c
··· 21 21 #include <asm/cpu_device_id.h> 22 22 #include <asm/intel-family.h> 23 23 24 - #define MSR_UNCORE_RATIO_LIMIT 0x620 25 - #define MSR_UNCORE_PERF_STATUS 0x621 26 - #define UNCORE_FREQ_KHZ_MULTIPLIER 100000 27 - 28 - /** 29 - * struct uncore_data - Encapsulate all uncore data 30 - * @stored_uncore_data: Last user changed MSR 620 value, which will be restored 31 - * on system resume. 32 - * @initial_min_freq_khz: Sampled minimum uncore frequency at driver init 33 - * @initial_max_freq_khz: Sampled maximum uncore frequency at driver init 34 - * @control_cpu: Designated CPU for a die to read/write 35 - * @valid: Mark the data valid/invalid 36 - * @package_id: Package id for this instance 37 - * @die_id: Die id for this instance 38 - * @name: Sysfs entry name for this instance 39 - * @uncore_attr_group: Attribute group storage 40 - * @max_freq_khz_dev_attr: Storage for device attribute max_freq_khz 41 - * @mix_freq_khz_dev_attr: Storage for device attribute min_freq_khz 42 - * @initial_max_freq_khz_dev_attr: Storage for device attribute initial_max_freq_khz 43 - * @initial_min_freq_khz_dev_attr: Storage for device attribute initial_min_freq_khz 44 - * @current_freq_khz_dev_attr: Storage for device attribute current_freq_khz 45 - * @uncore_attrs: Attribute storage for group creation 46 - * 47 - * This structure is used to encapsulate all data related to uncore sysfs 48 - * settings for a die/package. 49 - */ 50 - struct uncore_data { 51 - u64 stored_uncore_data; 52 - u32 initial_min_freq_khz; 53 - u32 initial_max_freq_khz; 54 - int control_cpu; 55 - bool valid; 56 - int package_id; 57 - int die_id; 58 - char name[32]; 59 - 60 - struct attribute_group uncore_attr_group; 61 - struct device_attribute max_freq_khz_dev_attr; 62 - struct device_attribute min_freq_khz_dev_attr; 63 - struct device_attribute initial_max_freq_khz_dev_attr; 64 - struct device_attribute initial_min_freq_khz_dev_attr; 65 - struct device_attribute current_freq_khz_dev_attr; 66 - struct attribute *uncore_attrs[6]; 67 - }; 24 + #include "uncore-frequency-common.h" 68 25 69 26 /* Max instances for uncore data, one for each die */ 70 27 static int uncore_max_entries __read_mostly; 71 28 /* Storage for uncore data for all instances */ 72 29 static struct uncore_data *uncore_instances; 73 - /* Root of the all uncore sysfs kobjs */ 74 - static struct kobject *uncore_root_kobj; 75 30 /* Stores the CPU mask of the target CPUs to use during uncore read/write */ 76 31 static cpumask_t uncore_cpu_mask; 77 32 /* CPU online callback register instance */ 78 33 static enum cpuhp_state uncore_hp_state __read_mostly; 79 - /* Mutex to control all mutual exclusions */ 80 - static DEFINE_MUTEX(uncore_lock); 81 34 82 - /* Common function to read MSR 0x620 and read min/max */ 83 - static int uncore_read_ratio(struct uncore_data *data, unsigned int *min, 84 - unsigned int *max) 35 + #define MSR_UNCORE_RATIO_LIMIT 0x620 36 + #define MSR_UNCORE_PERF_STATUS 0x621 37 + #define UNCORE_FREQ_KHZ_MULTIPLIER 100000 38 + 39 + static int uncore_read_control_freq(struct uncore_data *data, unsigned int *min, 40 + unsigned int *max) 85 41 { 86 42 u64 cap; 87 43 int ret; ··· 55 99 return 0; 56 100 } 57 101 58 - /* Common function to set min/max ratios to be used by sysfs callbacks */ 59 - static int uncore_write_ratio(struct uncore_data *data, unsigned int input, 60 - int set_max) 102 + static int uncore_write_control_freq(struct uncore_data *data, unsigned int input, 103 + unsigned int min_max) 61 104 { 62 105 int ret; 63 106 u64 cap; 64 - 65 - if (data->control_cpu < 0) 66 - return -ENXIO; 67 107 68 108 input /= UNCORE_FREQ_KHZ_MULTIPLIER; 69 109 if (!input || input > 0x7F) 70 110 return -EINVAL; 71 111 112 + if (data->control_cpu < 0) 113 + return -ENXIO; 114 + 72 115 ret = rdmsrl_on_cpu(data->control_cpu, MSR_UNCORE_RATIO_LIMIT, &cap); 73 116 if (ret) 74 117 return ret; 75 118 76 - if (set_max) { 119 + if (min_max) { 77 120 cap &= ~0x7F; 78 121 cap |= input; 79 122 } else { ··· 94 139 u64 ratio; 95 140 int ret; 96 141 142 + if (data->control_cpu < 0) 143 + return -ENXIO; 144 + 97 145 ret = rdmsrl_on_cpu(data->control_cpu, MSR_UNCORE_PERF_STATUS, &ratio); 98 146 if (ret) 99 147 return ret; ··· 104 146 *freq = (ratio & 0x7F) * UNCORE_FREQ_KHZ_MULTIPLIER; 105 147 106 148 return 0; 107 - } 108 - 109 - static ssize_t show_perf_status_freq_khz(struct uncore_data *data, char *buf) 110 - { 111 - unsigned int freq; 112 - int ret; 113 - 114 - mutex_lock(&uncore_lock); 115 - ret = uncore_read_freq(data, &freq); 116 - mutex_unlock(&uncore_lock); 117 - if (ret) 118 - return ret; 119 - 120 - return sprintf(buf, "%u\n", freq); 121 - } 122 - 123 - static ssize_t store_min_max_freq_khz(struct uncore_data *data, 124 - const char *buf, ssize_t count, 125 - int min_max) 126 - { 127 - unsigned int input; 128 - 129 - if (kstrtouint(buf, 10, &input)) 130 - return -EINVAL; 131 - 132 - mutex_lock(&uncore_lock); 133 - uncore_write_ratio(data, input, min_max); 134 - mutex_unlock(&uncore_lock); 135 - 136 - return count; 137 - } 138 - 139 - static ssize_t show_min_max_freq_khz(struct uncore_data *data, 140 - char *buf, int min_max) 141 - { 142 - unsigned int min, max; 143 - int ret; 144 - 145 - mutex_lock(&uncore_lock); 146 - ret = uncore_read_ratio(data, &min, &max); 147 - mutex_unlock(&uncore_lock); 148 - if (ret) 149 - return ret; 150 - 151 - if (min_max) 152 - return sprintf(buf, "%u\n", max); 153 - 154 - return sprintf(buf, "%u\n", min); 155 - } 156 - 157 - #define store_uncore_min_max(name, min_max) \ 158 - static ssize_t store_##name(struct device *dev, \ 159 - struct device_attribute *attr, \ 160 - const char *buf, size_t count) \ 161 - { \ 162 - struct uncore_data *data = container_of(attr, struct uncore_data, name##_dev_attr);\ 163 - \ 164 - return store_min_max_freq_khz(data, buf, count, \ 165 - min_max); \ 166 - } 167 - 168 - #define show_uncore_min_max(name, min_max) \ 169 - static ssize_t show_##name(struct device *dev, \ 170 - struct device_attribute *attr, char *buf)\ 171 - { \ 172 - struct uncore_data *data = container_of(attr, struct uncore_data, name##_dev_attr);\ 173 - \ 174 - return show_min_max_freq_khz(data, buf, min_max); \ 175 - } 176 - 177 - #define show_uncore_perf_status(name) \ 178 - static ssize_t show_##name(struct device *dev, \ 179 - struct device_attribute *attr, char *buf)\ 180 - { \ 181 - struct uncore_data *data = container_of(attr, struct uncore_data, name##_dev_attr);\ 182 - \ 183 - return show_perf_status_freq_khz(data, buf); \ 184 - } 185 - 186 - store_uncore_min_max(min_freq_khz, 0); 187 - store_uncore_min_max(max_freq_khz, 1); 188 - 189 - show_uncore_min_max(min_freq_khz, 0); 190 - show_uncore_min_max(max_freq_khz, 1); 191 - 192 - show_uncore_perf_status(current_freq_khz); 193 - 194 - #define show_uncore_data(member_name) \ 195 - static ssize_t show_##member_name(struct device *dev, \ 196 - struct device_attribute *attr, char *buf)\ 197 - { \ 198 - struct uncore_data *data = container_of(attr, struct uncore_data,\ 199 - member_name##_dev_attr);\ 200 - \ 201 - return scnprintf(buf, PAGE_SIZE, "%u\n", \ 202 - data->member_name); \ 203 - } \ 204 - 205 - show_uncore_data(initial_min_freq_khz); 206 - show_uncore_data(initial_max_freq_khz); 207 - 208 - #define init_attribute_rw(_name) \ 209 - do { \ 210 - sysfs_attr_init(&data->_name##_dev_attr.attr); \ 211 - data->_name##_dev_attr.show = show_##_name; \ 212 - data->_name##_dev_attr.store = store_##_name; \ 213 - data->_name##_dev_attr.attr.name = #_name; \ 214 - data->_name##_dev_attr.attr.mode = 0644; \ 215 - } while (0) 216 - 217 - #define init_attribute_ro(_name) \ 218 - do { \ 219 - sysfs_attr_init(&data->_name##_dev_attr.attr); \ 220 - data->_name##_dev_attr.show = show_##_name; \ 221 - data->_name##_dev_attr.store = NULL; \ 222 - data->_name##_dev_attr.attr.name = #_name; \ 223 - data->_name##_dev_attr.attr.mode = 0444; \ 224 - } while (0) 225 - 226 - #define init_attribute_root_ro(_name) \ 227 - do { \ 228 - sysfs_attr_init(&data->_name##_dev_attr.attr); \ 229 - data->_name##_dev_attr.show = show_##_name; \ 230 - data->_name##_dev_attr.store = NULL; \ 231 - data->_name##_dev_attr.attr.name = #_name; \ 232 - data->_name##_dev_attr.attr.mode = 0400; \ 233 - } while (0) 234 - 235 - static int create_attr_group(struct uncore_data *data, char *name) 236 - { 237 - int ret, index = 0; 238 - 239 - init_attribute_rw(max_freq_khz); 240 - init_attribute_rw(min_freq_khz); 241 - init_attribute_ro(initial_min_freq_khz); 242 - init_attribute_ro(initial_max_freq_khz); 243 - init_attribute_root_ro(current_freq_khz); 244 - 245 - data->uncore_attrs[index++] = &data->max_freq_khz_dev_attr.attr; 246 - data->uncore_attrs[index++] = &data->min_freq_khz_dev_attr.attr; 247 - data->uncore_attrs[index++] = &data->initial_min_freq_khz_dev_attr.attr; 248 - data->uncore_attrs[index++] = &data->initial_max_freq_khz_dev_attr.attr; 249 - data->uncore_attrs[index++] = &data->current_freq_khz_dev_attr.attr; 250 - data->uncore_attrs[index] = NULL; 251 - 252 - data->uncore_attr_group.name = name; 253 - data->uncore_attr_group.attrs = data->uncore_attrs; 254 - ret = sysfs_create_group(uncore_root_kobj, &data->uncore_attr_group); 255 - 256 - return ret; 257 - } 258 - 259 - static void delete_attr_group(struct uncore_data *data, char *name) 260 - { 261 - sysfs_remove_group(uncore_root_kobj, &data->uncore_attr_group); 262 149 } 263 150 264 151 /* Caller provides protection */ ··· 117 314 return NULL; 118 315 } 119 316 120 - static void uncore_add_die_entry(int cpu) 121 - { 122 - struct uncore_data *data; 123 - 124 - mutex_lock(&uncore_lock); 125 - data = uncore_get_instance(cpu); 126 - if (!data) { 127 - mutex_unlock(&uncore_lock); 128 - return; 129 - } 130 - 131 - if (data->valid) { 132 - /* control cpu changed */ 133 - data->control_cpu = cpu; 134 - } else { 135 - int ret; 136 - 137 - memset(data, 0, sizeof(*data)); 138 - sprintf(data->name, "package_%02d_die_%02d", 139 - topology_physical_package_id(cpu), 140 - topology_die_id(cpu)); 141 - 142 - uncore_read_ratio(data, &data->initial_min_freq_khz, 143 - &data->initial_max_freq_khz); 144 - 145 - ret = create_attr_group(data, data->name); 146 - if (!ret) { 147 - data->control_cpu = cpu; 148 - data->valid = true; 149 - } 150 - } 151 - mutex_unlock(&uncore_lock); 152 - } 153 - 154 - /* Last CPU in this die is offline, make control cpu invalid */ 155 - static void uncore_remove_die_entry(int cpu) 156 - { 157 - struct uncore_data *data; 158 - 159 - mutex_lock(&uncore_lock); 160 - data = uncore_get_instance(cpu); 161 - if (data) { 162 - delete_attr_group(data, data->name); 163 - data->control_cpu = -1; 164 - data->valid = false; 165 - } 166 - mutex_unlock(&uncore_lock); 167 - } 168 - 169 317 static int uncore_event_cpu_online(unsigned int cpu) 170 318 { 319 + struct uncore_data *data; 171 320 int target; 172 321 173 322 /* Check if there is an online cpu in the package for uncore MSR */ ··· 129 374 130 375 /* Use this CPU on this die as a control CPU */ 131 376 cpumask_set_cpu(cpu, &uncore_cpu_mask); 132 - uncore_add_die_entry(cpu); 133 377 134 - return 0; 378 + data = uncore_get_instance(cpu); 379 + if (!data) 380 + return 0; 381 + 382 + data->package_id = topology_physical_package_id(cpu); 383 + data->die_id = topology_die_id(cpu); 384 + 385 + return uncore_freq_add_entry(data, cpu); 135 386 } 136 387 137 388 static int uncore_event_cpu_offline(unsigned int cpu) 138 389 { 390 + struct uncore_data *data; 139 391 int target; 392 + 393 + data = uncore_get_instance(cpu); 394 + if (!data) 395 + return 0; 140 396 141 397 /* Check if existing cpu is used for uncore MSRs */ 142 398 if (!cpumask_test_and_clear_cpu(cpu, &uncore_cpu_mask)) ··· 158 392 159 393 if (target < nr_cpu_ids) { 160 394 cpumask_set_cpu(target, &uncore_cpu_mask); 161 - uncore_add_die_entry(target); 395 + uncore_freq_add_entry(data, target); 162 396 } else { 163 - uncore_remove_die_entry(cpu); 397 + uncore_freq_remove_die_entry(data); 164 398 } 165 399 166 400 return 0; ··· 169 403 static int uncore_pm_notify(struct notifier_block *nb, unsigned long mode, 170 404 void *_unused) 171 405 { 172 - int cpu; 406 + int i; 173 407 174 408 switch (mode) { 175 409 case PM_POST_HIBERNATION: 176 410 case PM_POST_RESTORE: 177 411 case PM_POST_SUSPEND: 178 - for_each_cpu(cpu, &uncore_cpu_mask) { 179 - struct uncore_data *data; 180 - int ret; 412 + for (i = 0; i < uncore_max_entries; ++i) { 413 + struct uncore_data *data = &uncore_instances[i]; 181 414 182 - data = uncore_get_instance(cpu); 183 415 if (!data || !data->valid || !data->stored_uncore_data) 184 - continue; 416 + return 0; 185 417 186 - ret = wrmsrl_on_cpu(cpu, MSR_UNCORE_RATIO_LIMIT, 187 - data->stored_uncore_data); 188 - if (ret) 189 - return ret; 418 + wrmsrl_on_cpu(data->control_cpu, MSR_UNCORE_RATIO_LIMIT, 419 + data->stored_uncore_data); 190 420 } 191 421 break; 192 422 default: ··· 205 443 X86_MATCH_INTEL_FAM6_MODEL(SAPPHIRERAPIDS_X, NULL), 206 444 {} 207 445 }; 446 + MODULE_DEVICE_TABLE(x86cpu, intel_uncore_cpu_ids); 208 447 209 448 static int __init intel_uncore_init(void) 210 449 { ··· 223 460 if (!uncore_instances) 224 461 return -ENOMEM; 225 462 226 - uncore_root_kobj = kobject_create_and_add("intel_uncore_frequency", 227 - &cpu_subsys.dev_root->kobj); 228 - if (!uncore_root_kobj) { 229 - ret = -ENOMEM; 463 + ret = uncore_freq_common_init(uncore_read_control_freq, uncore_write_control_freq, 464 + uncore_read_freq); 465 + if (!ret) 230 466 goto err_free; 231 - } 232 467 233 468 ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, 234 469 "platform/x86/uncore-freq:online", ··· 246 485 err_rem_state: 247 486 cpuhp_remove_state(uncore_hp_state); 248 487 err_rem_kobj: 249 - kobject_put(uncore_root_kobj); 488 + uncore_freq_common_exit(); 250 489 err_free: 251 490 kfree(uncore_instances); 252 491 ··· 256 495 257 496 static void __exit intel_uncore_exit(void) 258 497 { 498 + int i; 499 + 259 500 unregister_pm_notifier(&uncore_pm_nb); 260 501 cpuhp_remove_state(uncore_hp_state); 261 - kobject_put(uncore_root_kobj); 502 + for (i = 0; i < uncore_max_entries; ++i) 503 + uncore_freq_remove_die_entry(&uncore_instances[i]); 504 + uncore_freq_common_exit(); 262 505 kfree(uncore_instances); 263 506 } 264 507 module_exit(intel_uncore_exit) 265 508 509 + MODULE_IMPORT_NS(INTEL_UNCORE_FREQUENCY); 266 510 MODULE_LICENSE("GPL v2"); 267 511 MODULE_DESCRIPTION("Intel Uncore Frequency Limits Driver");