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: Use sysfs API to create attributes

Use of sysfs API is always preferable over using kobject calls to create
attributes. Remove usage of kobject_init_and_add() and use
sysfs_create_group(). To create relationship between sysfs attribute
and uncore instance use device_attribute*, which is defined per
uncore instance.

To create uniform locking for both read and write attributes take
lock in the sysfs callbacks, not in the actual functions where
the MSRs are read or updated.

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

authored by

Srinivas Pandruvada and committed by
Hans de Goede
ae7b2ce5 ce2645c4

+113 -112
+113 -112
drivers/platform/x86/intel/uncore-frequency/uncore-frequency.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 /* 3 3 * Intel Uncore Frequency Setting 4 - * Copyright (c) 2019, Intel Corporation. 4 + * Copyright (c) 2022, Intel Corporation. 5 5 * All rights reserved. 6 6 * 7 7 * Provide interface to set MSR 620 at a granularity of per die. On CPU online, ··· 32 32 * @initial_max_freq_khz: Sampled maximum uncore frequency at driver init 33 33 * @control_cpu: Designated CPU for a die to read/write 34 34 * @valid: Mark the data valid/invalid 35 + * @package_id: Package id for this instance 36 + * @die_id: Die id for this instance 37 + * @name: Sysfs entry name for this instance 38 + * @uncore_attr_group: Attribute group storage 39 + * @max_freq_khz_dev_attr: Storage for device attribute max_freq_khz 40 + * @mix_freq_khz_dev_attr: Storage for device attribute min_freq_khz 41 + * @initial_max_freq_khz_dev_attr: Storage for device attribute initial_max_freq_khz 42 + * @initial_min_freq_khz_dev_attr: Storage for device attribute initial_min_freq_khz 43 + * @uncore_attrs: Attribute storage for group creation 35 44 * 36 45 * This structure is used to encapsulate all data related to uncore sysfs 37 46 * settings for a die/package. 38 47 */ 39 48 struct uncore_data { 40 - struct kobject kobj; 41 - struct completion kobj_unregister; 42 49 u64 stored_uncore_data; 43 50 u32 initial_min_freq_khz; 44 51 u32 initial_max_freq_khz; 45 52 int control_cpu; 46 53 bool valid; 47 - }; 54 + int package_id; 55 + int die_id; 56 + char name[32]; 48 57 49 - #define to_uncore_data(a) container_of(a, struct uncore_data, kobj) 58 + struct attribute_group uncore_attr_group; 59 + struct device_attribute max_freq_khz_dev_attr; 60 + struct device_attribute min_freq_khz_dev_attr; 61 + struct device_attribute initial_max_freq_khz_dev_attr; 62 + struct device_attribute initial_min_freq_khz_dev_attr; 63 + struct attribute *uncore_attrs[5]; 64 + }; 50 65 51 66 /* Max instances for uncore data, one for each die */ 52 67 static int uncore_max_entries __read_mostly; ··· 75 60 static enum cpuhp_state uncore_hp_state __read_mostly; 76 61 /* Mutex to control all mutual exclusions */ 77 62 static DEFINE_MUTEX(uncore_lock); 78 - 79 - struct uncore_attr { 80 - struct attribute attr; 81 - ssize_t (*show)(struct kobject *kobj, 82 - struct attribute *attr, char *buf); 83 - ssize_t (*store)(struct kobject *kobj, 84 - struct attribute *attr, const char *c, ssize_t count); 85 - }; 86 - 87 - #define define_one_uncore_ro(_name) \ 88 - static struct uncore_attr _name = \ 89 - __ATTR(_name, 0444, show_##_name, NULL) 90 - 91 - #define define_one_uncore_rw(_name) \ 92 - static struct uncore_attr _name = \ 93 - __ATTR(_name, 0644, show_##_name, store_##_name) 94 - 95 - #define show_uncore_data(member_name) \ 96 - static ssize_t show_##member_name(struct kobject *kobj, \ 97 - struct attribute *attr, \ 98 - char *buf) \ 99 - { \ 100 - struct uncore_data *data = to_uncore_data(kobj); \ 101 - return scnprintf(buf, PAGE_SIZE, "%u\n", \ 102 - data->member_name); \ 103 - } \ 104 - define_one_uncore_ro(member_name) 105 - 106 - show_uncore_data(initial_min_freq_khz); 107 - show_uncore_data(initial_max_freq_khz); 108 63 109 64 /* Common function to read MSR 0x620 and read min/max */ 110 65 static int uncore_read_ratio(struct uncore_data *data, unsigned int *min, ··· 103 118 int ret; 104 119 u64 cap; 105 120 106 - mutex_lock(&uncore_lock); 107 - 108 - if (data->control_cpu < 0) { 109 - ret = -ENXIO; 110 - goto finish_write; 111 - } 121 + if (data->control_cpu < 0) 122 + return -ENXIO; 112 123 113 124 input /= UNCORE_FREQ_KHZ_MULTIPLIER; 114 - if (!input || input > 0x7F) { 115 - ret = -EINVAL; 116 - goto finish_write; 117 - } 125 + if (!input || input > 0x7F) 126 + return -EINVAL; 118 127 119 128 ret = rdmsrl_on_cpu(data->control_cpu, MSR_UNCORE_RATIO_LIMIT, &cap); 120 129 if (ret) 121 - goto finish_write; 130 + return ret; 122 131 123 132 if (set_max) { 124 133 cap &= ~0x7F; ··· 124 145 125 146 ret = wrmsrl_on_cpu(data->control_cpu, MSR_UNCORE_RATIO_LIMIT, cap); 126 147 if (ret) 127 - goto finish_write; 148 + return ret; 128 149 129 150 data->stored_uncore_data = cap; 130 151 131 - finish_write: 132 - mutex_unlock(&uncore_lock); 133 - 134 - return ret; 152 + return 0; 135 153 } 136 154 137 - static ssize_t store_min_max_freq_khz(struct kobject *kobj, 138 - struct attribute *attr, 139 - const char *buf, ssize_t count, 140 - int min_max) 141 - { 142 - struct uncore_data *data = to_uncore_data(kobj); 143 - unsigned int input; 144 - 145 - if (kstrtouint(buf, 10, &input)) 146 - return -EINVAL; 147 - 148 - uncore_write_ratio(data, input, min_max); 149 - 150 - return count; 151 - } 152 - 153 - static ssize_t show_min_max_freq_khz(struct kobject *kobj, 154 - struct attribute *attr, 155 + static ssize_t show_min_max_freq_khz(struct uncore_data *data, 155 156 char *buf, int min_max) 156 157 { 157 - struct uncore_data *data = to_uncore_data(kobj); 158 158 unsigned int min, max; 159 159 int ret; 160 160 ··· 149 191 return sprintf(buf, "%u\n", min); 150 192 } 151 193 194 + static ssize_t store_min_max_freq_khz(struct uncore_data *data, 195 + const char *buf, ssize_t count, 196 + int min_max) 197 + { 198 + unsigned int input; 199 + 200 + if (kstrtouint(buf, 10, &input)) 201 + return -EINVAL; 202 + 203 + mutex_lock(&uncore_lock); 204 + uncore_write_ratio(data, input, min_max); 205 + mutex_unlock(&uncore_lock); 206 + 207 + return count; 208 + } 209 + 152 210 #define store_uncore_min_max(name, min_max) \ 153 - static ssize_t store_##name(struct kobject *kobj, \ 154 - struct attribute *attr, \ 155 - const char *buf, ssize_t count) \ 156 - { \ 211 + static ssize_t store_##name(struct device *dev, \ 212 + struct device_attribute *attr, \ 213 + const char *buf, size_t count) \ 214 + { \ 215 + struct uncore_data *data = container_of(attr, struct uncore_data, name##_dev_attr);\ 157 216 \ 158 - return store_min_max_freq_khz(kobj, attr, buf, count, \ 159 - min_max); \ 217 + return store_min_max_freq_khz(data, buf, count, \ 218 + min_max); \ 160 219 } 161 220 162 221 #define show_uncore_min_max(name, min_max) \ 163 - static ssize_t show_##name(struct kobject *kobj, \ 164 - struct attribute *attr, char *buf) \ 222 + static ssize_t show_##name(struct device *dev, \ 223 + struct device_attribute *attr, char *buf)\ 165 224 { \ 225 + struct uncore_data *data = container_of(attr, struct uncore_data, name##_dev_attr);\ 166 226 \ 167 - return show_min_max_freq_khz(kobj, attr, buf, min_max); \ 227 + return show_min_max_freq_khz(data, buf, min_max); \ 168 228 } 169 229 170 230 store_uncore_min_max(min_freq_khz, 0); ··· 191 215 show_uncore_min_max(min_freq_khz, 0); 192 216 show_uncore_min_max(max_freq_khz, 1); 193 217 194 - define_one_uncore_rw(min_freq_khz); 195 - define_one_uncore_rw(max_freq_khz); 218 + #define show_uncore_data(member_name) \ 219 + static ssize_t show_##member_name(struct device *dev, \ 220 + struct device_attribute *attr, char *buf)\ 221 + { \ 222 + struct uncore_data *data = container_of(attr, struct uncore_data,\ 223 + member_name##_dev_attr);\ 224 + \ 225 + return scnprintf(buf, PAGE_SIZE, "%u\n", \ 226 + data->member_name); \ 227 + } \ 196 228 197 - static struct attribute *uncore_attrs[] = { 198 - &initial_min_freq_khz.attr, 199 - &initial_max_freq_khz.attr, 200 - &max_freq_khz.attr, 201 - &min_freq_khz.attr, 202 - NULL 203 - }; 204 - ATTRIBUTE_GROUPS(uncore); 229 + show_uncore_data(initial_min_freq_khz); 230 + show_uncore_data(initial_max_freq_khz); 205 231 206 - static void uncore_sysfs_entry_release(struct kobject *kobj) 232 + #define init_attribute_rw(_name) \ 233 + do { \ 234 + sysfs_attr_init(&data->_name##_dev_attr.attr); \ 235 + data->_name##_dev_attr.show = show_##_name; \ 236 + data->_name##_dev_attr.store = store_##_name; \ 237 + data->_name##_dev_attr.attr.name = #_name; \ 238 + data->_name##_dev_attr.attr.mode = 0644; \ 239 + } while (0) 240 + 241 + #define init_attribute_ro(_name) \ 242 + do { \ 243 + sysfs_attr_init(&data->_name##_dev_attr.attr); \ 244 + data->_name##_dev_attr.show = show_##_name; \ 245 + data->_name##_dev_attr.store = NULL; \ 246 + data->_name##_dev_attr.attr.name = #_name; \ 247 + data->_name##_dev_attr.attr.mode = 0444; \ 248 + } while (0) 249 + 250 + static int create_attr_group(struct uncore_data *data, char *name) 207 251 { 208 - struct uncore_data *data = to_uncore_data(kobj); 252 + int ret, index = 0; 209 253 210 - complete(&data->kobj_unregister); 254 + init_attribute_rw(max_freq_khz); 255 + init_attribute_rw(min_freq_khz); 256 + init_attribute_ro(initial_min_freq_khz); 257 + init_attribute_ro(initial_max_freq_khz); 258 + 259 + data->uncore_attrs[index++] = &data->max_freq_khz_dev_attr.attr; 260 + data->uncore_attrs[index++] = &data->min_freq_khz_dev_attr.attr; 261 + data->uncore_attrs[index++] = &data->initial_min_freq_khz_dev_attr.attr; 262 + data->uncore_attrs[index++] = &data->initial_max_freq_khz_dev_attr.attr; 263 + data->uncore_attrs[index] = NULL; 264 + 265 + data->uncore_attr_group.name = name; 266 + data->uncore_attr_group.attrs = data->uncore_attrs; 267 + ret = sysfs_create_group(uncore_root_kobj, &data->uncore_attr_group); 268 + 269 + return ret; 211 270 } 212 271 213 - static struct kobj_type uncore_ktype = { 214 - .release = uncore_sysfs_entry_release, 215 - .sysfs_ops = &kobj_sysfs_ops, 216 - .default_groups = uncore_groups, 217 - }; 272 + static void delete_attr_group(struct uncore_data *data, char *name) 273 + { 274 + sysfs_remove_group(uncore_root_kobj, &data->uncore_attr_group); 275 + } 218 276 219 277 /* Caller provides protection */ 220 278 static struct uncore_data *uncore_get_instance(unsigned int cpu) ··· 276 266 /* control cpu changed */ 277 267 data->control_cpu = cpu; 278 268 } else { 279 - char str[64]; 280 269 int ret; 281 270 282 271 memset(data, 0, sizeof(*data)); 283 - sprintf(str, "package_%02d_die_%02d", 272 + sprintf(data->name, "package_%02d_die_%02d", 284 273 topology_physical_package_id(cpu), 285 274 topology_die_id(cpu)); 286 275 287 276 uncore_read_ratio(data, &data->initial_min_freq_khz, 288 277 &data->initial_max_freq_khz); 289 278 290 - init_completion(&data->kobj_unregister); 291 - 292 - ret = kobject_init_and_add(&data->kobj, &uncore_ktype, 293 - uncore_root_kobj, str); 279 + ret = create_attr_group(data, data->name); 294 280 if (!ret) { 295 281 data->control_cpu = cpu; 296 282 data->valid = true; ··· 302 296 303 297 mutex_lock(&uncore_lock); 304 298 data = uncore_get_instance(cpu); 305 - if (data) 299 + if (data) { 300 + delete_attr_group(data, data->name); 306 301 data->control_cpu = -1; 302 + data->valid = false; 303 + } 307 304 mutex_unlock(&uncore_lock); 308 305 } 309 306 ··· 442 433 443 434 static void __exit intel_uncore_exit(void) 444 435 { 445 - int i; 446 - 447 436 unregister_pm_notifier(&uncore_pm_nb); 448 437 cpuhp_remove_state(uncore_hp_state); 449 - for (i = 0; i < uncore_max_entries; ++i) { 450 - if (uncore_instances[i].valid) { 451 - kobject_put(&uncore_instances[i].kobj); 452 - wait_for_completion(&uncore_instances[i].kobj_unregister); 453 - } 454 - } 455 438 kobject_put(uncore_root_kobj); 456 439 kfree(uncore_instances); 457 440 }