Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F147912586
D55604.id172966.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
10 KB
Referenced Files
None
Subscribers
None
D55604.id172966.diff
View Options
diff --git a/sys/x86/cpufreq/hwpstate_amd.c b/sys/x86/cpufreq/hwpstate_amd.c
--- a/sys/x86/cpufreq/hwpstate_amd.c
+++ b/sys/x86/cpufreq/hwpstate_amd.c
@@ -154,6 +154,13 @@
#define HWPFL_CPPC_REQUEST_NOT_READ (1 << 1)
#define HWPFL_CPPC_CPUFREQ_WRITE (1 << 2)
+struct hwpstate_cpufreq_methods {
+ int (*get)(device_t dev, struct cf_setting *cf);
+ int (*set)(device_t dev, const struct cf_setting *cf);
+ int (*settings)(device_t dev, struct cf_setting *sets, int *count);
+ int (*type)(device_t dev, int *type);
+};
+
/*
* Atomicity is achieved by only modifying a given softc on its associated CPU
* and with interrupts disabled.
@@ -163,6 +170,7 @@
struct hwpstate_softc {
device_t dev;
u_int flags;
+ struct hwpstate_cpufreq_methods *cpufreq_methods;
union {
struct {
struct hwpstate_setting
@@ -656,33 +664,36 @@
}
static int
-hwpstate_set(device_t dev, const struct cf_setting *cf)
+hwpstate_set_cppc(device_t dev, const struct cf_setting *cf)
{
struct hwpstate_softc *sc;
- struct hwpstate_setting *set;
uint32_t des_perf;
- int i;
- if (cf == NULL)
- return (EINVAL);
sc = device_get_softc(dev);
- if ((sc->flags & HWPFL_USE_CPPC) != 0) {
- if ((sc->flags & HWPFL_CPPC_CPUFREQ_WRITE) == 0)
- return (EOPNOTSUPP);
- des_perf = downscale_cppc_freq(sc, cf->freq);
- if (des_perf < BITS_VALUE(AMD_CPPC_CAPS_1_LOWEST_PERF_BITS,
- sc->cppc.caps1) ||
- des_perf > BITS_VALUE(AMD_CPPC_CAPS_1_HIGHEST_PERF_BITS,
- sc->cppc.caps1))
- return (ENXIO);
- SET_BITS_VALUE(sc->cppc.request, AMD_CPPC_REQUEST_DES_PERF_BITS,
- des_perf);
- return (x86_msr_op(MSR_AMD_CPPC_REQUEST,
- MSR_OP_RENDEZVOUS_ONE | MSR_OP_WRITE |
- MSR_OP_CPUID(cpu_get_pcpu(dev)->pc_cpuid),
- sc->cppc.request, NULL));
- }
+ if ((sc->flags & HWPFL_CPPC_CPUFREQ_WRITE) == 0)
+ return (EOPNOTSUPP);
+ des_perf = downscale_cppc_freq(sc, cf->freq);
+ if (des_perf <
+ BITS_VALUE(AMD_CPPC_CAPS_1_LOWEST_PERF_BITS, sc->cppc.caps1) ||
+ des_perf >
+ BITS_VALUE(AMD_CPPC_CAPS_1_HIGHEST_PERF_BITS, sc->cppc.caps1))
+ return (ENXIO);
+ SET_BITS_VALUE(sc->cppc.request, AMD_CPPC_REQUEST_DES_PERF_BITS,
+ des_perf);
+ return (x86_msr_op(MSR_AMD_CPPC_REQUEST,
+ MSR_OP_RENDEZVOUS_ONE | MSR_OP_WRITE |
+ MSR_OP_CPUID(cpu_get_pcpu(dev)->pc_cpuid),
+ sc->cppc.request, NULL));
+}
+
+static int
+hwpstate_set_pstate(device_t dev, const struct cf_setting *cf)
+{
+ struct hwpstate_softc *sc;
+ struct hwpstate_setting *set;
+ int i;
+ sc = device_get_softc(dev);
set = sc->hwpstate_settings;
for (i = 0; i < sc->cfnum; i++)
if (CPUFREQ_CMP(cf->freq, set[i].freq))
@@ -693,121 +704,170 @@
}
static int
-hwpstate_get(device_t dev, struct cf_setting *cf)
+hwpstate_set(device_t dev, const struct cf_setting *cf)
+{
+ struct hwpstate_softc *sc = device_get_softc(dev);
+
+ if (cf == NULL)
+ return (EINVAL);
+ return (sc->cpufreq_methods->set(dev, cf));
+}
+
+static int
+hwpstate_get_cppc(device_t dev, struct cf_setting *cf)
{
- struct hwpstate_softc *sc;
- struct hwpstate_setting set;
struct pcpu *pc;
- uint64_t msr;
uint64_t rate;
int ret;
+ pc = cpu_get_pcpu(dev);
+ if (pc == NULL)
+ return (ENXIO);
+
+ memset(cf, CPUFREQ_VAL_UNKNOWN, sizeof(*cf));
+ cf->dev = dev;
+ if ((ret = cpu_est_clockrate(pc->pc_cpuid, &rate)))
+ return (ret);
+ cf->freq = rate / 1000000;
+ return (0);
+}
+
+static int
+hwpstate_get_pstate(device_t dev, struct cf_setting *cf)
+{
+ struct hwpstate_softc *sc;
+ struct hwpstate_setting set;
+ uint64_t msr;
+
sc = device_get_softc(dev);
- if (cf == NULL)
+ msr = rdmsr(MSR_AMD_10H_11H_STATUS);
+ if (msr >= sc->cfnum)
return (EINVAL);
+ set = sc->hwpstate_settings[msr];
- if ((sc->flags & HWPFL_USE_CPPC) != 0) {
- pc = cpu_get_pcpu(dev);
- if (pc == NULL)
- return (ENXIO);
-
- memset(cf, CPUFREQ_VAL_UNKNOWN, sizeof(*cf));
- cf->dev = dev;
- if ((ret = cpu_est_clockrate(pc->pc_cpuid, &rate)))
- return (ret);
- cf->freq = rate / 1000000;
- } else {
- msr = rdmsr(MSR_AMD_10H_11H_STATUS);
- if (msr >= sc->cfnum)
- return (EINVAL);
- set = sc->hwpstate_settings[msr];
-
- cf->freq = set.freq;
- cf->volts = set.volts;
- cf->power = set.power;
- cf->lat = set.lat;
- cf->dev = dev;
- }
+ cf->freq = set.freq;
+ cf->volts = set.volts;
+ cf->power = set.power;
+ cf->lat = set.lat;
+ cf->dev = dev;
return (0);
}
+static int
+hwpstate_get(device_t dev, struct cf_setting *cf)
+{
+ struct hwpstate_softc *sc;
+
+ sc = device_get_softc(dev);
+ if (cf == NULL)
+ return (EINVAL);
+ return (sc->cpufreq_methods->get(dev, cf));
+}
+
#define AMD_CPPC_STEPS 10
#define AMD_CPPC_COUNT_LEVELS(l, r) \
(roundup(r - l + 1, AMD_CPPC_STEPS) / AMD_CPPC_STEPS)
static int
-hwpstate_settings(device_t dev, struct cf_setting *sets, int *count)
+hwpstate_settings_cppc(device_t dev, struct cf_setting *sets, int *count)
{
struct hwpstate_softc *sc;
- struct hwpstate_setting set;
int i;
int levels;
int cur_level;
- if (sets == NULL || count == NULL)
- return (EINVAL);
sc = device_get_softc(dev);
- if ((sc->flags & HWPFL_USE_CPPC) != 0) {
- if ((sc->flags & HWPFL_CPPC_CPUFREQ_WRITE) == 0)
- return (EOPNOTSUPP);
- levels = AMD_CPPC_COUNT_LEVELS(
- BITS_VALUE(AMD_CPPC_CAPS_1_LOWEST_PERF_BITS,
- sc->cppc.caps1),
+ if ((sc->flags & HWPFL_CPPC_CPUFREQ_WRITE) == 0)
+ return (EOPNOTSUPP);
+ levels = AMD_CPPC_COUNT_LEVELS(
+ BITS_VALUE(AMD_CPPC_CAPS_1_LOWEST_PERF_BITS, sc->cppc.caps1),
+ BITS_VALUE(AMD_CPPC_CAPS_1_HIGHEST_PERF_BITS, sc->cppc.caps1));
+ if (*count < levels)
+ return (E2BIG);
+ *count = levels;
+ cur_level = BITS_VALUE(AMD_CPPC_CAPS_1_LOWEST_PERF_BITS,
+ sc->cppc.caps1);
+ for (i = 0; i < levels; i++, sets++) {
+ sets->freq = upscale_cppc_freq(sc, cur_level);
+ sets->volts = CPUFREQ_VAL_UNKNOWN;
+ sets->power = CPUFREQ_VAL_UNKNOWN;
+ sets->lat = CPUFREQ_VAL_UNKNOWN;
+ sets->dev = dev;
+ cur_level += AMD_CPPC_STEPS;
+ cur_level = MIN(cur_level,
BITS_VALUE(AMD_CPPC_CAPS_1_HIGHEST_PERF_BITS,
sc->cppc.caps1));
- if (*count < levels)
- return (E2BIG);
- *count = levels;
- cur_level = BITS_VALUE(AMD_CPPC_CAPS_1_LOWEST_PERF_BITS,
- sc->cppc.caps1);
- for (i = 0; i < levels; i++, sets++) {
- sets->freq = upscale_cppc_freq(sc, cur_level);
- sets->volts = CPUFREQ_VAL_UNKNOWN;
- sets->power = CPUFREQ_VAL_UNKNOWN;
- sets->lat = CPUFREQ_VAL_UNKNOWN;
- sets->dev = dev;
- cur_level += AMD_CPPC_STEPS;
- cur_level = MIN(cur_level,
- BITS_VALUE(AMD_CPPC_CAPS_1_HIGHEST_PERF_BITS,
- sc->cppc.caps1));
- }
- } else {
- if (*count < sc->cfnum)
- return (E2BIG);
- for (i = 0; i < sc->cfnum; i++, sets++) {
- set = sc->hwpstate_settings[i];
- sets->freq = set.freq;
- sets->volts = set.volts;
- sets->power = set.power;
- sets->lat = set.lat;
- sets->dev = dev;
- }
- *count = sc->cfnum;
}
return (0);
}
static int
-hwpstate_type(device_t dev, int *type)
+hwpstate_settings_pstate(device_t dev, struct cf_setting *sets, int *count)
+{
+ struct hwpstate_setting set;
+ struct hwpstate_softc *sc;
+ int i;
+
+ sc = device_get_softc(dev);
+ if (*count < sc->cfnum)
+ return (E2BIG);
+ for (i = 0; i < sc->cfnum; i++, sets++) {
+ set = sc->hwpstate_settings[i];
+ sets->freq = set.freq;
+ sets->volts = set.volts;
+ sets->power = set.power;
+ sets->lat = set.lat;
+ sets->dev = dev;
+ }
+ *count = sc->cfnum;
+
+ return (0);
+}
+
+static int
+hwpstate_settings(device_t dev, struct cf_setting *sets, int *count)
{
struct hwpstate_softc *sc;
- if (type == NULL)
+ if (sets == NULL || count == NULL)
return (EINVAL);
+ sc = device_get_softc(dev);
+ return (sc->cpufreq_methods->settings(dev, sets, count));
+}
+
+static int
+hwpstate_type_cppc(device_t dev, int *type)
+{
+ struct hwpstate_softc *sc;
+
*type = CPUFREQ_TYPE_ABSOLUTE;
sc = device_get_softc(dev);
- if ((sc->flags & HWPFL_USE_CPPC)) {
- if ((sc->flags & HWPFL_CPPC_CPUFREQ_WRITE) == 0)
- *type |= CPUFREQ_FLAG_INFO_ONLY | CPUFREQ_FLAG_UNCACHED;
- }
+ if ((sc->flags & HWPFL_CPPC_CPUFREQ_WRITE) == 0)
+ *type |= CPUFREQ_FLAG_INFO_ONLY | CPUFREQ_FLAG_UNCACHED;
+
+ return (0);
+}
+static int
+hwpstate_type_pstate(device_t dev, int *type)
+{
+ *type = CPUFREQ_TYPE_ABSOLUTE;
return (0);
}
+static int
+hwpstate_type(device_t dev, int *type)
+{
+ struct hwpstate_softc *sc;
+
+ sc = device_get_softc(dev);
+ return (sc->cpufreq_methods->type(dev, type));
+}
+
static void
hwpstate_identify(driver_t *driver, device_t parent)
{
@@ -994,34 +1054,14 @@
}
static int
-hwpstate_probe(device_t dev)
+hwpstate_probe_pstate(device_t dev)
{
struct hwpstate_softc *sc;
device_t perf_dev;
- uint64_t msr;
int error, type;
+ uint64_t msr;
sc = device_get_softc(dev);
-
- if (hwpstate_amd_cppc_enable &&
- (amd_extended_feature_extensions & AMDFEID_CPPC)) {
- sc->flags |= HWPFL_USE_CPPC;
- device_set_desc(dev,
- "AMD Collaborative Processor Performance Control (CPPC)");
- } else {
- /*
- * No CPPC support. Only keep hwpstate0, it goes well with
- * acpi_throttle.
- */
- if (device_get_unit(dev) != 0)
- return (ENXIO);
- device_set_desc(dev, "Cool`n'Quiet 2.0");
- }
-
- sc->dev = dev;
- if ((sc->flags & HWPFL_USE_CPPC) != 0)
- return (0);
-
/*
* Check if acpi_perf has INFO only flag.
*/
@@ -1069,10 +1109,47 @@
*/
if (error)
error = hwpstate_get_info_from_msr(dev);
- if (error)
- return (error);
+ return (error);
+}
- return (0);
+struct hwpstate_cpufreq_methods cppc_methods = { .get = hwpstate_get_cppc,
+ .set = hwpstate_set_cppc,
+ .settings = hwpstate_settings_cppc,
+ .type = hwpstate_type_cppc };
+
+struct hwpstate_cpufreq_methods pstate_methods = { .get = hwpstate_get_pstate,
+ .set = hwpstate_set_pstate,
+ .settings = hwpstate_settings_pstate,
+ .type = hwpstate_type_pstate };
+
+static int
+hwpstate_probe(device_t dev)
+{
+ struct hwpstate_softc *sc;
+ sc = device_get_softc(dev);
+
+ if (hwpstate_amd_cppc_enable &&
+ (amd_extended_feature_extensions & AMDFEID_CPPC)) {
+ sc->flags |= HWPFL_USE_CPPC;
+ device_set_desc(dev,
+ "AMD Collaborative Processor Performance Control (CPPC)");
+ } else {
+ /*
+ * No CPPC support. Only keep hwpstate0, it goes well with
+ * acpi_throttle.
+ */
+ if (device_get_unit(dev) != 0)
+ return (ENXIO);
+ device_set_desc(dev, "Cool`n'Quiet 2.0");
+ }
+
+ sc->dev = dev;
+ if ((sc->flags & HWPFL_USE_CPPC) != 0) {
+ sc->cpufreq_methods = &cppc_methods;
+ return (0);
+ }
+ sc->cpufreq_methods = &pstate_methods;
+ return (hwpstate_probe_pstate(dev));
}
static int
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Mar 15, 3:07 PM (1 h, 17 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29160784
Default Alt Text
D55604.id172966.diff (10 KB)
Attached To
Mode
D55604: hwpstate_amd: Refactor by brancless version
Attached
Detach File
Event Timeline
Log In to Comment