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>
This commit is contained in:
parent
ae7b2ce578
commit
414eef2728
1 changed files with 62 additions and 9 deletions
|
@ -22,6 +22,7 @@
|
||||||
#include <asm/intel-family.h>
|
#include <asm/intel-family.h>
|
||||||
|
|
||||||
#define MSR_UNCORE_RATIO_LIMIT 0x620
|
#define MSR_UNCORE_RATIO_LIMIT 0x620
|
||||||
|
#define MSR_UNCORE_PERF_STATUS 0x621
|
||||||
#define UNCORE_FREQ_KHZ_MULTIPLIER 100000
|
#define UNCORE_FREQ_KHZ_MULTIPLIER 100000
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -40,6 +41,7 @@
|
||||||
* @mix_freq_khz_dev_attr: Storage for device attribute min_freq_khz
|
* @mix_freq_khz_dev_attr: Storage for device attribute min_freq_khz
|
||||||
* @initial_max_freq_khz_dev_attr: Storage for device attribute initial_max_freq_khz
|
* @initial_max_freq_khz_dev_attr: Storage for device attribute initial_max_freq_khz
|
||||||
* @initial_min_freq_khz_dev_attr: Storage for device attribute initial_min_freq_khz
|
* @initial_min_freq_khz_dev_attr: Storage for device attribute initial_min_freq_khz
|
||||||
|
* @current_freq_khz_dev_attr: Storage for device attribute current_freq_khz
|
||||||
* @uncore_attrs: Attribute storage for group creation
|
* @uncore_attrs: Attribute storage for group creation
|
||||||
*
|
*
|
||||||
* This structure is used to encapsulate all data related to uncore sysfs
|
* This structure is used to encapsulate all data related to uncore sysfs
|
||||||
|
@ -60,7 +62,8 @@ struct uncore_data {
|
||||||
struct device_attribute min_freq_khz_dev_attr;
|
struct device_attribute min_freq_khz_dev_attr;
|
||||||
struct device_attribute initial_max_freq_khz_dev_attr;
|
struct device_attribute initial_max_freq_khz_dev_attr;
|
||||||
struct device_attribute initial_min_freq_khz_dev_attr;
|
struct device_attribute initial_min_freq_khz_dev_attr;
|
||||||
struct attribute *uncore_attrs[5];
|
struct device_attribute current_freq_khz_dev_attr;
|
||||||
|
struct attribute *uncore_attrs[6];
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Max instances for uncore data, one for each die */
|
/* Max instances for uncore data, one for each die */
|
||||||
|
@ -131,22 +134,32 @@ static int uncore_write_ratio(struct uncore_data *data, unsigned int input,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t show_min_max_freq_khz(struct uncore_data *data,
|
static int uncore_read_freq(struct uncore_data *data, unsigned int *freq)
|
||||||
char *buf, int min_max)
|
|
||||||
{
|
{
|
||||||
unsigned int min, max;
|
u64 ratio;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = rdmsrl_on_cpu(data->control_cpu, MSR_UNCORE_PERF_STATUS, &ratio);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
*freq = (ratio & 0x7F) * UNCORE_FREQ_KHZ_MULTIPLIER;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t show_perf_status_freq_khz(struct uncore_data *data, char *buf)
|
||||||
|
{
|
||||||
|
unsigned int freq;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
mutex_lock(&uncore_lock);
|
mutex_lock(&uncore_lock);
|
||||||
ret = uncore_read_ratio(data, &min, &max);
|
ret = uncore_read_freq(data, &freq);
|
||||||
mutex_unlock(&uncore_lock);
|
mutex_unlock(&uncore_lock);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (min_max)
|
return sprintf(buf, "%u\n", freq);
|
||||||
return sprintf(buf, "%u\n", max);
|
|
||||||
|
|
||||||
return sprintf(buf, "%u\n", min);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t store_min_max_freq_khz(struct uncore_data *data,
|
static ssize_t store_min_max_freq_khz(struct uncore_data *data,
|
||||||
|
@ -165,6 +178,24 @@ static ssize_t store_min_max_freq_khz(struct uncore_data *data,
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ssize_t show_min_max_freq_khz(struct uncore_data *data,
|
||||||
|
char *buf, int min_max)
|
||||||
|
{
|
||||||
|
unsigned int min, max;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
mutex_lock(&uncore_lock);
|
||||||
|
ret = uncore_read_ratio(data, &min, &max);
|
||||||
|
mutex_unlock(&uncore_lock);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (min_max)
|
||||||
|
return sprintf(buf, "%u\n", max);
|
||||||
|
|
||||||
|
return sprintf(buf, "%u\n", min);
|
||||||
|
}
|
||||||
|
|
||||||
#define store_uncore_min_max(name, min_max) \
|
#define store_uncore_min_max(name, min_max) \
|
||||||
static ssize_t store_##name(struct device *dev, \
|
static ssize_t store_##name(struct device *dev, \
|
||||||
struct device_attribute *attr, \
|
struct device_attribute *attr, \
|
||||||
|
@ -185,12 +216,23 @@ static ssize_t store_min_max_freq_khz(struct uncore_data *data,
|
||||||
return show_min_max_freq_khz(data, buf, min_max); \
|
return show_min_max_freq_khz(data, buf, min_max); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define show_uncore_perf_status(name) \
|
||||||
|
static ssize_t show_##name(struct device *dev, \
|
||||||
|
struct device_attribute *attr, char *buf)\
|
||||||
|
{ \
|
||||||
|
struct uncore_data *data = container_of(attr, struct uncore_data, name##_dev_attr);\
|
||||||
|
\
|
||||||
|
return show_perf_status_freq_khz(data, buf); \
|
||||||
|
}
|
||||||
|
|
||||||
store_uncore_min_max(min_freq_khz, 0);
|
store_uncore_min_max(min_freq_khz, 0);
|
||||||
store_uncore_min_max(max_freq_khz, 1);
|
store_uncore_min_max(max_freq_khz, 1);
|
||||||
|
|
||||||
show_uncore_min_max(min_freq_khz, 0);
|
show_uncore_min_max(min_freq_khz, 0);
|
||||||
show_uncore_min_max(max_freq_khz, 1);
|
show_uncore_min_max(max_freq_khz, 1);
|
||||||
|
|
||||||
|
show_uncore_perf_status(current_freq_khz);
|
||||||
|
|
||||||
#define show_uncore_data(member_name) \
|
#define show_uncore_data(member_name) \
|
||||||
static ssize_t show_##member_name(struct device *dev, \
|
static ssize_t show_##member_name(struct device *dev, \
|
||||||
struct device_attribute *attr, char *buf)\
|
struct device_attribute *attr, char *buf)\
|
||||||
|
@ -223,6 +265,15 @@ show_uncore_data(initial_max_freq_khz);
|
||||||
data->_name##_dev_attr.attr.mode = 0444; \
|
data->_name##_dev_attr.attr.mode = 0444; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#define init_attribute_root_ro(_name) \
|
||||||
|
do { \
|
||||||
|
sysfs_attr_init(&data->_name##_dev_attr.attr); \
|
||||||
|
data->_name##_dev_attr.show = show_##_name; \
|
||||||
|
data->_name##_dev_attr.store = NULL; \
|
||||||
|
data->_name##_dev_attr.attr.name = #_name; \
|
||||||
|
data->_name##_dev_attr.attr.mode = 0400; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
static int create_attr_group(struct uncore_data *data, char *name)
|
static int create_attr_group(struct uncore_data *data, char *name)
|
||||||
{
|
{
|
||||||
int ret, index = 0;
|
int ret, index = 0;
|
||||||
|
@ -231,11 +282,13 @@ static int create_attr_group(struct uncore_data *data, char *name)
|
||||||
init_attribute_rw(min_freq_khz);
|
init_attribute_rw(min_freq_khz);
|
||||||
init_attribute_ro(initial_min_freq_khz);
|
init_attribute_ro(initial_min_freq_khz);
|
||||||
init_attribute_ro(initial_max_freq_khz);
|
init_attribute_ro(initial_max_freq_khz);
|
||||||
|
init_attribute_root_ro(current_freq_khz);
|
||||||
|
|
||||||
data->uncore_attrs[index++] = &data->max_freq_khz_dev_attr.attr;
|
data->uncore_attrs[index++] = &data->max_freq_khz_dev_attr.attr;
|
||||||
data->uncore_attrs[index++] = &data->min_freq_khz_dev_attr.attr;
|
data->uncore_attrs[index++] = &data->min_freq_khz_dev_attr.attr;
|
||||||
data->uncore_attrs[index++] = &data->initial_min_freq_khz_dev_attr.attr;
|
data->uncore_attrs[index++] = &data->initial_min_freq_khz_dev_attr.attr;
|
||||||
data->uncore_attrs[index++] = &data->initial_max_freq_khz_dev_attr.attr;
|
data->uncore_attrs[index++] = &data->initial_max_freq_khz_dev_attr.attr;
|
||||||
|
data->uncore_attrs[index++] = &data->current_freq_khz_dev_attr.attr;
|
||||||
data->uncore_attrs[index] = NULL;
|
data->uncore_attrs[index] = NULL;
|
||||||
|
|
||||||
data->uncore_attr_group.name = name;
|
data->uncore_attr_group.name = name;
|
||||||
|
|
Loading…
Add table
Reference in a new issue