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: Display uncore current frequency

Add a new sysfs attribute "current_freq_khz" to display current uncore
frequency. This value is read from MSR 0x621.

Root user permission is required to read uncore current frequency.

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-4-srinivas.pandruvada@linux.intel.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>

authored by

Srinivas Pandruvada and committed by
Hans de Goede
414eef27 ae7b2ce5

+62 -9
+62 -9
drivers/platform/x86/intel/uncore-frequency/uncore-frequency.c
··· 22 22 #include <asm/intel-family.h> 23 23 24 24 #define MSR_UNCORE_RATIO_LIMIT 0x620 25 + #define MSR_UNCORE_PERF_STATUS 0x621 25 26 #define UNCORE_FREQ_KHZ_MULTIPLIER 100000 26 27 27 28 /** ··· 41 40 * @mix_freq_khz_dev_attr: Storage for device attribute min_freq_khz 42 41 * @initial_max_freq_khz_dev_attr: Storage for device attribute initial_max_freq_khz 43 42 * @initial_min_freq_khz_dev_attr: Storage for device attribute initial_min_freq_khz 43 + * @current_freq_khz_dev_attr: Storage for device attribute current_freq_khz 44 44 * @uncore_attrs: Attribute storage for group creation 45 45 * 46 46 * This structure is used to encapsulate all data related to uncore sysfs ··· 62 60 struct device_attribute min_freq_khz_dev_attr; 63 61 struct device_attribute initial_max_freq_khz_dev_attr; 64 62 struct device_attribute initial_min_freq_khz_dev_attr; 65 - struct attribute *uncore_attrs[5]; 63 + struct device_attribute current_freq_khz_dev_attr; 64 + struct attribute *uncore_attrs[6]; 66 65 }; 67 66 68 67 /* Max instances for uncore data, one for each die */ ··· 134 131 return 0; 135 132 } 136 133 137 - static ssize_t show_min_max_freq_khz(struct uncore_data *data, 138 - char *buf, int min_max) 134 + static int uncore_read_freq(struct uncore_data *data, unsigned int *freq) 139 135 { 140 - unsigned int min, max; 136 + u64 ratio; 137 + int ret; 138 + 139 + ret = rdmsrl_on_cpu(data->control_cpu, MSR_UNCORE_PERF_STATUS, &ratio); 140 + if (ret) 141 + return ret; 142 + 143 + *freq = (ratio & 0x7F) * UNCORE_FREQ_KHZ_MULTIPLIER; 144 + 145 + return 0; 146 + } 147 + 148 + static ssize_t show_perf_status_freq_khz(struct uncore_data *data, char *buf) 149 + { 150 + unsigned int freq; 141 151 int ret; 142 152 143 153 mutex_lock(&uncore_lock); 144 - ret = uncore_read_ratio(data, &min, &max); 154 + ret = uncore_read_freq(data, &freq); 145 155 mutex_unlock(&uncore_lock); 146 156 if (ret) 147 157 return ret; 148 158 149 - if (min_max) 150 - return sprintf(buf, "%u\n", max); 151 - 152 - return sprintf(buf, "%u\n", min); 159 + return sprintf(buf, "%u\n", freq); 153 160 } 154 161 155 162 static ssize_t store_min_max_freq_khz(struct uncore_data *data, ··· 176 163 mutex_unlock(&uncore_lock); 177 164 178 165 return count; 166 + } 167 + 168 + static ssize_t show_min_max_freq_khz(struct uncore_data *data, 169 + char *buf, int min_max) 170 + { 171 + unsigned int min, max; 172 + int ret; 173 + 174 + mutex_lock(&uncore_lock); 175 + ret = uncore_read_ratio(data, &min, &max); 176 + mutex_unlock(&uncore_lock); 177 + if (ret) 178 + return ret; 179 + 180 + if (min_max) 181 + return sprintf(buf, "%u\n", max); 182 + 183 + return sprintf(buf, "%u\n", min); 179 184 } 180 185 181 186 #define store_uncore_min_max(name, min_max) \ ··· 216 185 return show_min_max_freq_khz(data, buf, min_max); \ 217 186 } 218 187 188 + #define show_uncore_perf_status(name) \ 189 + static ssize_t show_##name(struct device *dev, \ 190 + struct device_attribute *attr, char *buf)\ 191 + { \ 192 + struct uncore_data *data = container_of(attr, struct uncore_data, name##_dev_attr);\ 193 + \ 194 + return show_perf_status_freq_khz(data, buf); \ 195 + } 196 + 219 197 store_uncore_min_max(min_freq_khz, 0); 220 198 store_uncore_min_max(max_freq_khz, 1); 221 199 222 200 show_uncore_min_max(min_freq_khz, 0); 223 201 show_uncore_min_max(max_freq_khz, 1); 202 + 203 + show_uncore_perf_status(current_freq_khz); 224 204 225 205 #define show_uncore_data(member_name) \ 226 206 static ssize_t show_##member_name(struct device *dev, \ ··· 265 223 data->_name##_dev_attr.attr.mode = 0444; \ 266 224 } while (0) 267 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 + 268 235 static int create_attr_group(struct uncore_data *data, char *name) 269 236 { 270 237 int ret, index = 0; ··· 282 231 init_attribute_rw(min_freq_khz); 283 232 init_attribute_ro(initial_min_freq_khz); 284 233 init_attribute_ro(initial_max_freq_khz); 234 + init_attribute_root_ro(current_freq_khz); 285 235 286 236 data->uncore_attrs[index++] = &data->max_freq_khz_dev_attr.attr; 287 237 data->uncore_attrs[index++] = &data->min_freq_khz_dev_attr.attr; 288 238 data->uncore_attrs[index++] = &data->initial_min_freq_khz_dev_attr.attr; 289 239 data->uncore_attrs[index++] = &data->initial_max_freq_khz_dev_attr.attr; 240 + data->uncore_attrs[index++] = &data->current_freq_khz_dev_attr.attr; 290 241 data->uncore_attrs[index] = NULL; 291 242 292 243 data->uncore_attr_group.name = name;