0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/cpu.h>
0009 #include <linux/module.h>
0010 #include "uncore-frequency-common.h"
0011
0012
0013 static DEFINE_MUTEX(uncore_lock);
0014
0015 static struct kobject *uncore_root_kobj;
0016
0017 static int uncore_instance_count;
0018
0019
0020 static int (*uncore_read)(struct uncore_data *data, unsigned int *min, unsigned int *max);
0021 static int (*uncore_write)(struct uncore_data *data, unsigned int input, unsigned int min_max);
0022 static int (*uncore_read_freq)(struct uncore_data *data, unsigned int *freq);
0023
0024 static ssize_t show_min_max_freq_khz(struct uncore_data *data,
0025 char *buf, int min_max)
0026 {
0027 unsigned int min, max;
0028 int ret;
0029
0030 mutex_lock(&uncore_lock);
0031 ret = uncore_read(data, &min, &max);
0032 mutex_unlock(&uncore_lock);
0033 if (ret)
0034 return ret;
0035
0036 if (min_max)
0037 return sprintf(buf, "%u\n", max);
0038
0039 return sprintf(buf, "%u\n", min);
0040 }
0041
0042 static ssize_t store_min_max_freq_khz(struct uncore_data *data,
0043 const char *buf, ssize_t count,
0044 int min_max)
0045 {
0046 unsigned int input;
0047
0048 if (kstrtouint(buf, 10, &input))
0049 return -EINVAL;
0050
0051 mutex_lock(&uncore_lock);
0052 uncore_write(data, input, min_max);
0053 mutex_unlock(&uncore_lock);
0054
0055 return count;
0056 }
0057
0058 static ssize_t show_perf_status_freq_khz(struct uncore_data *data, char *buf)
0059 {
0060 unsigned int freq;
0061 int ret;
0062
0063 mutex_lock(&uncore_lock);
0064 ret = uncore_read_freq(data, &freq);
0065 mutex_unlock(&uncore_lock);
0066 if (ret)
0067 return ret;
0068
0069 return sprintf(buf, "%u\n", freq);
0070 }
0071
0072 #define store_uncore_min_max(name, min_max) \
0073 static ssize_t store_##name(struct device *dev, \
0074 struct device_attribute *attr, \
0075 const char *buf, size_t count) \
0076 { \
0077 struct uncore_data *data = container_of(attr, struct uncore_data, name##_dev_attr);\
0078 \
0079 return store_min_max_freq_khz(data, buf, count, \
0080 min_max); \
0081 }
0082
0083 #define show_uncore_min_max(name, min_max) \
0084 static ssize_t show_##name(struct device *dev, \
0085 struct device_attribute *attr, char *buf)\
0086 { \
0087 struct uncore_data *data = container_of(attr, struct uncore_data, name##_dev_attr);\
0088 \
0089 return show_min_max_freq_khz(data, buf, min_max); \
0090 }
0091
0092 #define show_uncore_perf_status(name) \
0093 static ssize_t show_##name(struct device *dev, \
0094 struct device_attribute *attr, char *buf)\
0095 { \
0096 struct uncore_data *data = container_of(attr, struct uncore_data, name##_dev_attr);\
0097 \
0098 return show_perf_status_freq_khz(data, buf); \
0099 }
0100
0101 store_uncore_min_max(min_freq_khz, 0);
0102 store_uncore_min_max(max_freq_khz, 1);
0103
0104 show_uncore_min_max(min_freq_khz, 0);
0105 show_uncore_min_max(max_freq_khz, 1);
0106
0107 show_uncore_perf_status(current_freq_khz);
0108
0109 #define show_uncore_data(member_name) \
0110 static ssize_t show_##member_name(struct device *dev, \
0111 struct device_attribute *attr, char *buf)\
0112 { \
0113 struct uncore_data *data = container_of(attr, struct uncore_data,\
0114 member_name##_dev_attr);\
0115 \
0116 return scnprintf(buf, PAGE_SIZE, "%u\n", \
0117 data->member_name); \
0118 } \
0119
0120 show_uncore_data(initial_min_freq_khz);
0121 show_uncore_data(initial_max_freq_khz);
0122
0123 #define init_attribute_rw(_name) \
0124 do { \
0125 sysfs_attr_init(&data->_name##_dev_attr.attr); \
0126 data->_name##_dev_attr.show = show_##_name; \
0127 data->_name##_dev_attr.store = store_##_name; \
0128 data->_name##_dev_attr.attr.name = #_name; \
0129 data->_name##_dev_attr.attr.mode = 0644; \
0130 } while (0)
0131
0132 #define init_attribute_ro(_name) \
0133 do { \
0134 sysfs_attr_init(&data->_name##_dev_attr.attr); \
0135 data->_name##_dev_attr.show = show_##_name; \
0136 data->_name##_dev_attr.store = NULL; \
0137 data->_name##_dev_attr.attr.name = #_name; \
0138 data->_name##_dev_attr.attr.mode = 0444; \
0139 } while (0)
0140
0141 #define init_attribute_root_ro(_name) \
0142 do { \
0143 sysfs_attr_init(&data->_name##_dev_attr.attr); \
0144 data->_name##_dev_attr.show = show_##_name; \
0145 data->_name##_dev_attr.store = NULL; \
0146 data->_name##_dev_attr.attr.name = #_name; \
0147 data->_name##_dev_attr.attr.mode = 0400; \
0148 } while (0)
0149
0150 static int create_attr_group(struct uncore_data *data, char *name)
0151 {
0152 int ret, index = 0;
0153
0154 init_attribute_rw(max_freq_khz);
0155 init_attribute_rw(min_freq_khz);
0156 init_attribute_ro(initial_min_freq_khz);
0157 init_attribute_ro(initial_max_freq_khz);
0158 init_attribute_root_ro(current_freq_khz);
0159
0160 data->uncore_attrs[index++] = &data->max_freq_khz_dev_attr.attr;
0161 data->uncore_attrs[index++] = &data->min_freq_khz_dev_attr.attr;
0162 data->uncore_attrs[index++] = &data->initial_min_freq_khz_dev_attr.attr;
0163 data->uncore_attrs[index++] = &data->initial_max_freq_khz_dev_attr.attr;
0164 data->uncore_attrs[index++] = &data->current_freq_khz_dev_attr.attr;
0165 data->uncore_attrs[index] = NULL;
0166
0167 data->uncore_attr_group.name = name;
0168 data->uncore_attr_group.attrs = data->uncore_attrs;
0169 ret = sysfs_create_group(uncore_root_kobj, &data->uncore_attr_group);
0170
0171 return ret;
0172 }
0173
0174 static void delete_attr_group(struct uncore_data *data, char *name)
0175 {
0176 sysfs_remove_group(uncore_root_kobj, &data->uncore_attr_group);
0177 }
0178
0179 int uncore_freq_add_entry(struct uncore_data *data, int cpu)
0180 {
0181 int ret = 0;
0182
0183 mutex_lock(&uncore_lock);
0184 if (data->valid) {
0185
0186 data->control_cpu = cpu;
0187 goto uncore_unlock;
0188 }
0189
0190 sprintf(data->name, "package_%02d_die_%02d", data->package_id, data->die_id);
0191
0192 uncore_read(data, &data->initial_min_freq_khz, &data->initial_max_freq_khz);
0193
0194 ret = create_attr_group(data, data->name);
0195 if (!ret) {
0196 data->control_cpu = cpu;
0197 data->valid = true;
0198 }
0199
0200 uncore_unlock:
0201 mutex_unlock(&uncore_lock);
0202
0203 return ret;
0204 }
0205 EXPORT_SYMBOL_NS_GPL(uncore_freq_add_entry, INTEL_UNCORE_FREQUENCY);
0206
0207 void uncore_freq_remove_die_entry(struct uncore_data *data)
0208 {
0209 mutex_lock(&uncore_lock);
0210 delete_attr_group(data, data->name);
0211 data->control_cpu = -1;
0212 data->valid = false;
0213 mutex_unlock(&uncore_lock);
0214 }
0215 EXPORT_SYMBOL_NS_GPL(uncore_freq_remove_die_entry, INTEL_UNCORE_FREQUENCY);
0216
0217 int uncore_freq_common_init(int (*read_control_freq)(struct uncore_data *data, unsigned int *min, unsigned int *max),
0218 int (*write_control_freq)(struct uncore_data *data, unsigned int input, unsigned int set_max),
0219 int (*read_freq)(struct uncore_data *data, unsigned int *freq))
0220 {
0221 mutex_lock(&uncore_lock);
0222
0223 uncore_read = read_control_freq;
0224 uncore_write = write_control_freq;
0225 uncore_read_freq = read_freq;
0226
0227 if (!uncore_root_kobj)
0228 uncore_root_kobj = kobject_create_and_add("intel_uncore_frequency",
0229 &cpu_subsys.dev_root->kobj);
0230 if (uncore_root_kobj)
0231 ++uncore_instance_count;
0232 mutex_unlock(&uncore_lock);
0233
0234 return uncore_root_kobj ? 0 : -ENOMEM;
0235 }
0236 EXPORT_SYMBOL_NS_GPL(uncore_freq_common_init, INTEL_UNCORE_FREQUENCY);
0237
0238 void uncore_freq_common_exit(void)
0239 {
0240 mutex_lock(&uncore_lock);
0241 --uncore_instance_count;
0242 if (!uncore_instance_count) {
0243 kobject_put(uncore_root_kobj);
0244 uncore_root_kobj = NULL;
0245 }
0246 mutex_unlock(&uncore_lock);
0247 }
0248 EXPORT_SYMBOL_NS_GPL(uncore_freq_common_exit, INTEL_UNCORE_FREQUENCY);
0249
0250
0251 MODULE_LICENSE("GPL v2");
0252 MODULE_DESCRIPTION("Intel Uncore Frequency Common Module");