More ACPI and power management fixes and updates for 3.15-rc1
- Fix for a recently introduced CPU hotplug regression in ARM KVM from Ming Lei. - Fixes for breakage in the at32ap, loongson2_cpufreq, and unicore32 cpufreq drivers introduced during the 3.14 cycle (-stable material) from Chen Gang and Viresh Kumar. - New powernv cpufreq driver from Vaidyanathan Srinivasan, with bits from Gautham R Shenoy and Srivatsa S Bhat. - Exynos cpufreq driver fix preventing it from being included into multiplatform builds that aren't supported by it from Sachin Kamat. - cpufreq cleanups related to the usage of the driver_data field in struct cpufreq_frequency_table from Viresh Kumar. - cpufreq ppc driver cleanup from Sachin Kamat. - Intel BayTrail support for intel_idle and ACPI idle from Len Brown. - Intel CPU model 54 (Atom N2000 series) support for intel_idle from Jan Kiszka. - intel_idle fix for Intel Ivy Town residency targets from Len Brown. - turbostat updates (Intel Broadwell support and output cleanups) from Len Brown. - New cpuidle sysfs attribute for exporting C-states' target residency information to user space from Daniel Lezcano. - New kernel command line argument to prevent power domains enabled by the bootloader from being turned off even if they are not in use (for diagnostics purposes) from Tushar Behera. - Fixes for wakeup sysfs attributes documentation from Geert Uytterhoeven. - New ACPI video blacklist entry for ThinkPad Helix from Stephen Chandler Paul. - Assorted ACPI cleanups and a Kconfig help update from Jonghwan Choi, Zhihui Zhang, Hanjun Guo. / -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABCAAGBQJTRxLAAAoJEILEb/54YlRxnCwP/16UwO/eVE8SIi0TqQboikFC k8u7F3zgDYG+xPSzXlCR+J7thTxGueQlrb+aM18PYuMVgaw2rpy7U7SIqEk8s6oR uFnzZCWKA5ZebbZn+NlodnQaJmbgJxwsVJDuuechUka/e67CaIc54JULi2ynZ0lz Kg/nU3NJhu4S81cT5SOTkJ9xE63oxHcCwKbNqEmxn7x7ddFzGK/DThG67NMEnW1F vHbBTSyI6vmXXg1f9aobUtuo3PfJkkx5jD+nR1H2e6wmB64tW7JPVKV3mi6LJfYM ui/8/gNb3PUMHMX1QbL9EFbPxl9miQx2NJ7dgFKa1HZ/WPyiXpJjz7uGr9O3Fau3 cFVREdaW8p2TAYWOEgH8luohhdK0j8UEpR/sEm0TrTjsK8wqczVf/hz6RraVJZiN ck6eVHjY6m3/bFQauZQ/r+DNeeNcdr+iLejgjbh/MXuF3j0kx+1dkKkzCEU2TgEZ 9etF0uzjlgyXySyxNKBeSW13+ssVA6kF5/BHns7LHoxTfGu7Y4oVaWUi+j74i66O bc+2ileNal71mS4v9gomnj6Ffj8oH8KXFA7k0sEsAdwLZNgThB5bTppmY/U7Y5Ce hTS81tcGe2vOVQzF9iFOF7LNKKussAVAtrgkkrA8lJLeOTfQbIo4+fMhORxf3X/p 3O7R/jc4cT+IXK8a2xRt =hGKg -----END PGP SIGNATURE----- Merge tag 'pm+acpi-3.15-rc1-3' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm Pull more ACPI and power management fixes and updates from Rafael Wysocki: "This is PM and ACPI material that has emerged over the last two weeks and one fix for a CPU hotplug regression introduced by the recent CPU hotplug notifiers registration series. Included are intel_idle and turbostat updates from Len Brown (these have been in linux-next for quite some time), a new cpufreq driver for powernv (that might spend some more time in linux-next, but BenH was asking me so nicely to push it for 3.15 that I couldn't resist), some cpufreq fixes and cleanups (including fixes for some silly breakage in a couple of cpufreq drivers introduced during the 3.14 cycle), assorted ACPI cleanups, wakeup framework documentation fixes, a new sysfs attribute for cpuidle and a new command line argument for power domains diagnostics. Specifics: - Fix for a recently introduced CPU hotplug regression in ARM KVM from Ming Lei. - Fixes for breakage in the at32ap, loongson2_cpufreq, and unicore32 cpufreq drivers introduced during the 3.14 cycle (-stable material) from Chen Gang and Viresh Kumar. - New powernv cpufreq driver from Vaidyanathan Srinivasan, with bits from Gautham R Shenoy and Srivatsa S Bhat. - Exynos cpufreq driver fix preventing it from being included into multiplatform builds that aren't supported by it from Sachin Kamat. - cpufreq cleanups related to the usage of the driver_data field in struct cpufreq_frequency_table from Viresh Kumar. - cpufreq ppc driver cleanup from Sachin Kamat. - Intel BayTrail support for intel_idle and ACPI idle from Len Brown. - Intel CPU model 54 (Atom N2000 series) support for intel_idle from Jan Kiszka. - intel_idle fix for Intel Ivy Town residency targets from Len Brown. - turbostat updates (Intel Broadwell support and output cleanups) from Len Brown. - New cpuidle sysfs attribute for exporting C-states' target residency information to user space from Daniel Lezcano. - New kernel command line argument to prevent power domains enabled by the bootloader from being turned off even if they are not in use (for diagnostics purposes) from Tushar Behera. - Fixes for wakeup sysfs attributes documentation from Geert Uytterhoeven. - New ACPI video blacklist entry for ThinkPad Helix from Stephen Chandler Paul. - Assorted ACPI cleanups and a Kconfig help update from Jonghwan Choi, Zhihui Zhang, Hanjun Guo" * tag 'pm+acpi-3.15-rc1-3' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (28 commits) ACPI: Update the ACPI spec information in Kconfig arm, kvm: fix double lock on cpu_add_remove_lock cpuidle: sysfs: Export target residency information cpufreq: ppc: Remove duplicate inclusion of fsl_soc.h cpufreq: create another field .flags in cpufreq_frequency_table cpufreq: use kzalloc() to allocate memory for cpufreq_frequency_table cpufreq: don't print value of .driver_data from core cpufreq: ia64: don't set .driver_data to index cpufreq: powernv: Select CPUFreq related Kconfig options for powernv cpufreq: powernv: Use cpufreq_frequency_table.driver_data to store pstate ids cpufreq: powernv: cpufreq driver for powernv platform cpufreq: at32ap: don't declare local variable as static cpufreq: loongson2_cpufreq: don't declare local variable as static cpufreq: unicore32: fix typo issue for 'clk' cpufreq: exynos: Disable on multiplatform build PM / wakeup: Correct presence vs. emptiness of wakeup_* attributes PM / domains: Add pd_ignore_unused to keep power domains enabled ACPI / dock: Drop dock_device_ids[] table ACPI / video: Favor native backlight interface for ThinkPad Helix ACPI / thermal: Fix wrong variable usage in debug statement ...
This commit is contained in:
commit
eeb91e4f9d
|
@ -83,8 +83,10 @@ Contact: Rafael J. Wysocki <rjw@rjwysocki.net>
|
|||
Description:
|
||||
The /sys/devices/.../wakeup_count attribute contains the number
|
||||
of signaled wakeup events associated with the device. This
|
||||
attribute is read-only. If the device is not enabled to wake up
|
||||
attribute is read-only. If the device is not capable to wake up
|
||||
the system from sleep states, this attribute is not present.
|
||||
If the device is not enabled to wake up the system from sleep
|
||||
states, this attribute is empty.
|
||||
|
||||
What: /sys/devices/.../power/wakeup_active_count
|
||||
Date: September 2010
|
||||
|
@ -93,8 +95,10 @@ Description:
|
|||
The /sys/devices/.../wakeup_active_count attribute contains the
|
||||
number of times the processing of wakeup events associated with
|
||||
the device was completed (at the kernel level). This attribute
|
||||
is read-only. If the device is not enabled to wake up the
|
||||
system from sleep states, this attribute is not present.
|
||||
is read-only. If the device is not capable to wake up the
|
||||
system from sleep states, this attribute is not present. If
|
||||
the device is not enabled to wake up the system from sleep
|
||||
states, this attribute is empty.
|
||||
|
||||
What: /sys/devices/.../power/wakeup_abort_count
|
||||
Date: February 2012
|
||||
|
@ -104,8 +108,9 @@ Description:
|
|||
number of times the processing of a wakeup event associated with
|
||||
the device might have aborted system transition into a sleep
|
||||
state in progress. This attribute is read-only. If the device
|
||||
is not enabled to wake up the system from sleep states, this
|
||||
attribute is not present.
|
||||
is not capable to wake up the system from sleep states, this
|
||||
attribute is not present. If the device is not enabled to wake
|
||||
up the system from sleep states, this attribute is empty.
|
||||
|
||||
What: /sys/devices/.../power/wakeup_expire_count
|
||||
Date: February 2012
|
||||
|
@ -114,8 +119,10 @@ Description:
|
|||
The /sys/devices/.../wakeup_expire_count attribute contains the
|
||||
number of times a wakeup event associated with the device has
|
||||
been reported with a timeout that expired. This attribute is
|
||||
read-only. If the device is not enabled to wake up the system
|
||||
from sleep states, this attribute is not present.
|
||||
read-only. If the device is not capable to wake up the system
|
||||
from sleep states, this attribute is not present. If the
|
||||
device is not enabled to wake up the system from sleep states,
|
||||
this attribute is empty.
|
||||
|
||||
What: /sys/devices/.../power/wakeup_active
|
||||
Date: September 2010
|
||||
|
@ -124,8 +131,10 @@ Description:
|
|||
The /sys/devices/.../wakeup_active attribute contains either 1,
|
||||
or 0, depending on whether or not a wakeup event associated with
|
||||
the device is being processed (1). This attribute is read-only.
|
||||
If the device is not enabled to wake up the system from sleep
|
||||
states, this attribute is not present.
|
||||
If the device is not capable to wake up the system from sleep
|
||||
states, this attribute is not present. If the device is not
|
||||
enabled to wake up the system from sleep states, this attribute
|
||||
is empty.
|
||||
|
||||
What: /sys/devices/.../power/wakeup_total_time_ms
|
||||
Date: September 2010
|
||||
|
@ -134,8 +143,9 @@ Description:
|
|||
The /sys/devices/.../wakeup_total_time_ms attribute contains
|
||||
the total time of processing wakeup events associated with the
|
||||
device, in milliseconds. This attribute is read-only. If the
|
||||
device is not enabled to wake up the system from sleep states,
|
||||
this attribute is not present.
|
||||
device is not capable to wake up the system from sleep states,
|
||||
this attribute is not present. If the device is not enabled to
|
||||
wake up the system from sleep states, this attribute is empty.
|
||||
|
||||
What: /sys/devices/.../power/wakeup_max_time_ms
|
||||
Date: September 2010
|
||||
|
@ -144,8 +154,10 @@ Description:
|
|||
The /sys/devices/.../wakeup_max_time_ms attribute contains
|
||||
the maximum time of processing a single wakeup event associated
|
||||
with the device, in milliseconds. This attribute is read-only.
|
||||
If the device is not enabled to wake up the system from sleep
|
||||
states, this attribute is not present.
|
||||
If the device is not capable to wake up the system from sleep
|
||||
states, this attribute is not present. If the device is not
|
||||
enabled to wake up the system from sleep states, this attribute
|
||||
is empty.
|
||||
|
||||
What: /sys/devices/.../power/wakeup_last_time_ms
|
||||
Date: September 2010
|
||||
|
@ -156,7 +168,8 @@ Description:
|
|||
signaling the last wakeup event associated with the device, in
|
||||
milliseconds. This attribute is read-only. If the device is
|
||||
not enabled to wake up the system from sleep states, this
|
||||
attribute is not present.
|
||||
attribute is not present. If the device is not enabled to wake
|
||||
up the system from sleep states, this attribute is empty.
|
||||
|
||||
What: /sys/devices/.../power/wakeup_prevent_sleep_time_ms
|
||||
Date: February 2012
|
||||
|
@ -165,9 +178,10 @@ Description:
|
|||
The /sys/devices/.../wakeup_prevent_sleep_time_ms attribute
|
||||
contains the total time the device has been preventing
|
||||
opportunistic transitions to sleep states from occurring.
|
||||
This attribute is read-only. If the device is not enabled to
|
||||
This attribute is read-only. If the device is not capable to
|
||||
wake up the system from sleep states, this attribute is not
|
||||
present.
|
||||
present. If the device is not enabled to wake up the system
|
||||
from sleep states, this attribute is empty.
|
||||
|
||||
What: /sys/devices/.../power/autosuspend_delay_ms
|
||||
Date: September 2010
|
||||
|
|
|
@ -2563,6 +2563,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
|||
|
||||
pcmv= [HW,PCMCIA] BadgePAD 4
|
||||
|
||||
pd_ignore_unused
|
||||
[PM]
|
||||
Keep all power-domains already enabled by bootloader on,
|
||||
even if no driver has claimed them. This is useful
|
||||
for debug and development, but should not be
|
||||
needed on a platform with proper driver support.
|
||||
|
||||
pd. [PARIDE]
|
||||
See Documentation/blockdev/paride.txt.
|
||||
|
||||
|
|
|
@ -28,16 +28,16 @@ enum {
|
|||
};
|
||||
|
||||
struct cpufreq_frequency_table loongson2_clockmod_table[] = {
|
||||
{DC_RESV, CPUFREQ_ENTRY_INVALID},
|
||||
{DC_ZERO, CPUFREQ_ENTRY_INVALID},
|
||||
{DC_25PT, 0},
|
||||
{DC_37PT, 0},
|
||||
{DC_50PT, 0},
|
||||
{DC_62PT, 0},
|
||||
{DC_75PT, 0},
|
||||
{DC_87PT, 0},
|
||||
{DC_DISABLE, 0},
|
||||
{DC_RESV, CPUFREQ_TABLE_END},
|
||||
{0, DC_RESV, CPUFREQ_ENTRY_INVALID},
|
||||
{0, DC_ZERO, CPUFREQ_ENTRY_INVALID},
|
||||
{0, DC_25PT, 0},
|
||||
{0, DC_37PT, 0},
|
||||
{0, DC_50PT, 0},
|
||||
{0, DC_62PT, 0},
|
||||
{0, DC_75PT, 0},
|
||||
{0, DC_87PT, 0},
|
||||
{0, DC_DISABLE, 0},
|
||||
{0, DC_RESV, CPUFREQ_TABLE_END},
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(loongson2_clockmod_table);
|
||||
|
||||
|
|
|
@ -306,3 +306,4 @@ CONFIG_KVM_BOOK3S_64=m
|
|||
CONFIG_KVM_BOOK3S_64_HV=y
|
||||
CONFIG_TRANSPARENT_HUGEPAGE=y
|
||||
CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y
|
||||
CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
|
||||
|
|
|
@ -301,3 +301,4 @@ CONFIG_CRYPTO_LZO=m
|
|||
# CONFIG_CRYPTO_ANSI_CPRNG is not set
|
||||
CONFIG_CRYPTO_DEV_NX=y
|
||||
CONFIG_CRYPTO_DEV_NX_ENCRYPT=m
|
||||
CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
|
||||
|
|
|
@ -272,6 +272,10 @@
|
|||
#define SPRN_HSRR1 0x13B /* Hypervisor Save/Restore 1 */
|
||||
#define SPRN_IC 0x350 /* Virtual Instruction Count */
|
||||
#define SPRN_VTB 0x351 /* Virtual Time Base */
|
||||
#define SPRN_PMICR 0x354 /* Power Management Idle Control Reg */
|
||||
#define SPRN_PMSR 0x355 /* Power Management Status Reg */
|
||||
#define SPRN_PMCR 0x374 /* Power Management Control Register */
|
||||
|
||||
/* HFSCR and FSCR bit numbers are the same */
|
||||
#define FSCR_TAR_LG 8 /* Enable Target Address Register */
|
||||
#define FSCR_EBB_LG 7 /* Enable Event Based Branching */
|
||||
|
|
|
@ -11,6 +11,12 @@ config PPC_POWERNV
|
|||
select PPC_UDBG_16550
|
||||
select PPC_SCOM
|
||||
select ARCH_RANDOM
|
||||
select CPU_FREQ
|
||||
select CPU_FREQ_GOV_PERFORMANCE
|
||||
select CPU_FREQ_GOV_POWERSAVE
|
||||
select CPU_FREQ_GOV_USERSPACE
|
||||
select CPU_FREQ_GOV_ONDEMAND
|
||||
select CPU_FREQ_GOV_CONSERVATIVE
|
||||
default y
|
||||
|
||||
config PPC_POWERNV_RTAS
|
||||
|
|
|
@ -87,7 +87,9 @@ static long acpi_processor_ffh_cstate_probe_cpu(void *_cx)
|
|||
num_cstate_subtype = edx_part & MWAIT_SUBSTATE_MASK;
|
||||
|
||||
retval = 0;
|
||||
if (num_cstate_subtype < (cx->address & MWAIT_SUBSTATE_MASK)) {
|
||||
/* If the HW does not support any sub-states in this C-state */
|
||||
if (num_cstate_subtype == 0) {
|
||||
pr_warn(FW_BUG "ACPI MWAIT C-state 0x%x not supported by HW (0x%x)\n", cx->address, edx_part);
|
||||
retval = -1;
|
||||
goto out;
|
||||
}
|
||||
|
|
|
@ -31,10 +31,14 @@ menuconfig ACPI
|
|||
ACPI CA, see:
|
||||
<http://acpica.org/>
|
||||
|
||||
ACPI is an open industry specification co-developed by
|
||||
Hewlett-Packard, Intel, Microsoft, Phoenix, and Toshiba.
|
||||
ACPI is an open industry specification originally co-developed by
|
||||
Hewlett-Packard, Intel, Microsoft, Phoenix, and Toshiba. Currently,
|
||||
it is developed by the ACPI Specification Working Group (ASWG) under
|
||||
the UEFI Forum and any UEFI member can join the ASWG and contribute
|
||||
to the ACPI specification.
|
||||
The specification is available at:
|
||||
<http://www.acpi.info>
|
||||
<http://www.uefi.org/acpi/specs>
|
||||
|
||||
if ACPI
|
||||
|
||||
|
|
|
@ -51,12 +51,6 @@ MODULE_PARM_DESC(immediate_undock, "1 (default) will cause the driver to "
|
|||
" the driver to wait for userspace to write the undock sysfs file "
|
||||
" before undocking");
|
||||
|
||||
static const struct acpi_device_id dock_device_ids[] = {
|
||||
{"LNXDOCK", 0},
|
||||
{"", 0},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, dock_device_ids);
|
||||
|
||||
struct dock_station {
|
||||
acpi_handle handle;
|
||||
unsigned long last_dock_time;
|
||||
|
|
|
@ -1219,10 +1219,9 @@ acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_handle * handle)
|
|||
{
|
||||
struct semaphore *sem = NULL;
|
||||
|
||||
sem = acpi_os_allocate(sizeof(struct semaphore));
|
||||
sem = acpi_os_allocate_zeroed(sizeof(struct semaphore));
|
||||
if (!sem)
|
||||
return AE_NO_MEMORY;
|
||||
memset(sem, 0, sizeof(struct semaphore));
|
||||
|
||||
sema_init(sem, initial_units);
|
||||
|
||||
|
|
|
@ -344,7 +344,7 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
|
|||
tz->trips.hot.flags.valid = 1;
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"Found hot threshold [%lu]\n",
|
||||
tz->trips.critical.temperature));
|
||||
tz->trips.hot.temperature));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -164,11 +164,10 @@ acpi_extract_package(union acpi_object *package,
|
|||
* Validate output buffer.
|
||||
*/
|
||||
if (buffer->length == ACPI_ALLOCATE_BUFFER) {
|
||||
buffer->pointer = ACPI_ALLOCATE(size_required);
|
||||
buffer->pointer = ACPI_ALLOCATE_ZEROED(size_required);
|
||||
if (!buffer->pointer)
|
||||
return AE_NO_MEMORY;
|
||||
buffer->length = size_required;
|
||||
memset(buffer->pointer, 0, size_required);
|
||||
} else {
|
||||
if (buffer->length < size_required) {
|
||||
buffer->length = size_required;
|
||||
|
|
|
@ -487,6 +487,14 @@ static struct dmi_system_id video_dmi_table[] __initdata = {
|
|||
DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo IdeaPad Yoga 13"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_set_use_native_backlight,
|
||||
.ident = "Thinkpad Helix",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad Helix"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_set_use_native_backlight,
|
||||
.ident = "Dell Inspiron 7520",
|
||||
|
|
|
@ -705,6 +705,14 @@ static int pm_genpd_runtime_resume(struct device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool pd_ignore_unused;
|
||||
static int __init pd_ignore_unused_setup(char *__unused)
|
||||
{
|
||||
pd_ignore_unused = true;
|
||||
return 1;
|
||||
}
|
||||
__setup("pd_ignore_unused", pd_ignore_unused_setup);
|
||||
|
||||
/**
|
||||
* pm_genpd_poweroff_unused - Power off all PM domains with no devices in use.
|
||||
*/
|
||||
|
@ -712,6 +720,11 @@ void pm_genpd_poweroff_unused(void)
|
|||
{
|
||||
struct generic_pm_domain *genpd;
|
||||
|
||||
if (pd_ignore_unused) {
|
||||
pr_warn("genpd: Not disabling unused power domains\n");
|
||||
return;
|
||||
}
|
||||
|
||||
mutex_lock(&gpd_list_lock);
|
||||
|
||||
list_for_each_entry(genpd, &gpd_list, gpd_list_node)
|
||||
|
|
|
@ -30,7 +30,7 @@ config ARM_EXYNOS_CPUFREQ
|
|||
|
||||
config ARM_EXYNOS4210_CPUFREQ
|
||||
bool "SAMSUNG EXYNOS4210"
|
||||
depends on CPU_EXYNOS4210
|
||||
depends on CPU_EXYNOS4210 && !ARCH_MULTIPLATFORM
|
||||
default y
|
||||
select ARM_EXYNOS_CPUFREQ
|
||||
help
|
||||
|
@ -41,7 +41,7 @@ config ARM_EXYNOS4210_CPUFREQ
|
|||
|
||||
config ARM_EXYNOS4X12_CPUFREQ
|
||||
bool "SAMSUNG EXYNOS4x12"
|
||||
depends on (SOC_EXYNOS4212 || SOC_EXYNOS4412)
|
||||
depends on (SOC_EXYNOS4212 || SOC_EXYNOS4412) && !ARCH_MULTIPLATFORM
|
||||
default y
|
||||
select ARM_EXYNOS_CPUFREQ
|
||||
help
|
||||
|
@ -52,7 +52,7 @@ config ARM_EXYNOS4X12_CPUFREQ
|
|||
|
||||
config ARM_EXYNOS5250_CPUFREQ
|
||||
bool "SAMSUNG EXYNOS5250"
|
||||
depends on SOC_EXYNOS5250
|
||||
depends on SOC_EXYNOS5250 && !ARCH_MULTIPLATFORM
|
||||
default y
|
||||
select ARM_EXYNOS_CPUFREQ
|
||||
help
|
||||
|
|
|
@ -54,3 +54,11 @@ config PPC_PASEMI_CPUFREQ
|
|||
help
|
||||
This adds the support for frequency switching on PA Semi
|
||||
PWRficient processors.
|
||||
|
||||
config POWERNV_CPUFREQ
|
||||
tristate "CPU frequency scaling for IBM POWERNV platform"
|
||||
depends on PPC_POWERNV
|
||||
default y
|
||||
help
|
||||
This adds support for CPU frequency switching on IBM POWERNV
|
||||
platform
|
||||
|
|
|
@ -86,6 +86,7 @@ obj-$(CONFIG_PPC_CORENET_CPUFREQ) += ppc-corenet-cpufreq.o
|
|||
obj-$(CONFIG_CPU_FREQ_PMAC) += pmac32-cpufreq.o
|
||||
obj-$(CONFIG_CPU_FREQ_PMAC64) += pmac64-cpufreq.o
|
||||
obj-$(CONFIG_PPC_PASEMI_CPUFREQ) += pasemi-cpufreq.o
|
||||
obj-$(CONFIG_POWERNV_CPUFREQ) += powernv-cpufreq.o
|
||||
|
||||
##################################################################################
|
||||
# Other platform drivers
|
||||
|
|
|
@ -754,7 +754,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
|
|||
goto err_unreg;
|
||||
}
|
||||
|
||||
data->freq_table = kmalloc(sizeof(*data->freq_table) *
|
||||
data->freq_table = kzalloc(sizeof(*data->freq_table) *
|
||||
(perf->state_count+1), GFP_KERNEL);
|
||||
if (!data->freq_table) {
|
||||
result = -ENOMEM;
|
||||
|
|
|
@ -52,7 +52,7 @@ static int at32_set_target(struct cpufreq_policy *policy, unsigned int index)
|
|||
static int at32_cpufreq_driver_init(struct cpufreq_policy *policy)
|
||||
{
|
||||
unsigned int frequency, rate, min_freq;
|
||||
static struct clk *cpuclk;
|
||||
struct clk *cpuclk;
|
||||
int retval, steps, i;
|
||||
|
||||
if (policy->cpu != 0)
|
||||
|
|
|
@ -15,9 +15,9 @@ static struct notifier_block cris_sdram_freq_notifier_block = {
|
|||
};
|
||||
|
||||
static struct cpufreq_frequency_table cris_freq_table[] = {
|
||||
{0x01, 6000},
|
||||
{0x02, 200000},
|
||||
{0, CPUFREQ_TABLE_END},
|
||||
{0, 0x01, 6000},
|
||||
{0, 0x02, 200000},
|
||||
{0, 0, CPUFREQ_TABLE_END},
|
||||
};
|
||||
|
||||
static unsigned int cris_freq_get_cpu_frequency(unsigned int cpu)
|
||||
|
|
|
@ -15,9 +15,9 @@ static struct notifier_block cris_sdram_freq_notifier_block = {
|
|||
};
|
||||
|
||||
static struct cpufreq_frequency_table cris_freq_table[] = {
|
||||
{0x01, 6000},
|
||||
{0x02, 200000},
|
||||
{0, CPUFREQ_TABLE_END},
|
||||
{0, 0x01, 6000},
|
||||
{0, 0x02, 200000},
|
||||
{0, 0, CPUFREQ_TABLE_END},
|
||||
};
|
||||
|
||||
static unsigned int cris_freq_get_cpu_frequency(unsigned int cpu)
|
||||
|
|
|
@ -56,15 +56,15 @@ static struct s_elan_multiplier elan_multiplier[] = {
|
|||
};
|
||||
|
||||
static struct cpufreq_frequency_table elanfreq_table[] = {
|
||||
{0, 1000},
|
||||
{1, 2000},
|
||||
{2, 4000},
|
||||
{3, 8000},
|
||||
{4, 16000},
|
||||
{5, 33000},
|
||||
{6, 66000},
|
||||
{7, 99000},
|
||||
{0, CPUFREQ_TABLE_END},
|
||||
{0, 0, 1000},
|
||||
{0, 1, 2000},
|
||||
{0, 2, 4000},
|
||||
{0, 3, 8000},
|
||||
{0, 4, 16000},
|
||||
{0, 5, 33000},
|
||||
{0, 6, 66000},
|
||||
{0, 7, 99000},
|
||||
{0, 0, CPUFREQ_TABLE_END},
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -29,12 +29,12 @@ static unsigned int exynos4210_volt_table[] = {
|
|||
};
|
||||
|
||||
static struct cpufreq_frequency_table exynos4210_freq_table[] = {
|
||||
{L0, 1200 * 1000},
|
||||
{L1, 1000 * 1000},
|
||||
{L2, 800 * 1000},
|
||||
{L3, 500 * 1000},
|
||||
{L4, 200 * 1000},
|
||||
{0, CPUFREQ_TABLE_END},
|
||||
{0, L0, 1200 * 1000},
|
||||
{0, L1, 1000 * 1000},
|
||||
{0, L2, 800 * 1000},
|
||||
{0, L3, 500 * 1000},
|
||||
{0, L4, 200 * 1000},
|
||||
{0, 0, CPUFREQ_TABLE_END},
|
||||
};
|
||||
|
||||
static struct apll_freq apll_freq_4210[] = {
|
||||
|
|
|
@ -30,21 +30,21 @@ static unsigned int exynos4x12_volt_table[] = {
|
|||
};
|
||||
|
||||
static struct cpufreq_frequency_table exynos4x12_freq_table[] = {
|
||||
{CPUFREQ_BOOST_FREQ, 1500 * 1000},
|
||||
{L1, 1400 * 1000},
|
||||
{L2, 1300 * 1000},
|
||||
{L3, 1200 * 1000},
|
||||
{L4, 1100 * 1000},
|
||||
{L5, 1000 * 1000},
|
||||
{L6, 900 * 1000},
|
||||
{L7, 800 * 1000},
|
||||
{L8, 700 * 1000},
|
||||
{L9, 600 * 1000},
|
||||
{L10, 500 * 1000},
|
||||
{L11, 400 * 1000},
|
||||
{L12, 300 * 1000},
|
||||
{L13, 200 * 1000},
|
||||
{0, CPUFREQ_TABLE_END},
|
||||
{CPUFREQ_BOOST_FREQ, L0, 1500 * 1000},
|
||||
{0, L1, 1400 * 1000},
|
||||
{0, L2, 1300 * 1000},
|
||||
{0, L3, 1200 * 1000},
|
||||
{0, L4, 1100 * 1000},
|
||||
{0, L5, 1000 * 1000},
|
||||
{0, L6, 900 * 1000},
|
||||
{0, L7, 800 * 1000},
|
||||
{0, L8, 700 * 1000},
|
||||
{0, L9, 600 * 1000},
|
||||
{0, L10, 500 * 1000},
|
||||
{0, L11, 400 * 1000},
|
||||
{0, L12, 300 * 1000},
|
||||
{0, L13, 200 * 1000},
|
||||
{0, 0, CPUFREQ_TABLE_END},
|
||||
};
|
||||
|
||||
static struct apll_freq *apll_freq_4x12;
|
||||
|
|
|
@ -34,23 +34,23 @@ static unsigned int exynos5250_volt_table[] = {
|
|||
};
|
||||
|
||||
static struct cpufreq_frequency_table exynos5250_freq_table[] = {
|
||||
{L0, 1700 * 1000},
|
||||
{L1, 1600 * 1000},
|
||||
{L2, 1500 * 1000},
|
||||
{L3, 1400 * 1000},
|
||||
{L4, 1300 * 1000},
|
||||
{L5, 1200 * 1000},
|
||||
{L6, 1100 * 1000},
|
||||
{L7, 1000 * 1000},
|
||||
{L8, 900 * 1000},
|
||||
{L9, 800 * 1000},
|
||||
{L10, 700 * 1000},
|
||||
{L11, 600 * 1000},
|
||||
{L12, 500 * 1000},
|
||||
{L13, 400 * 1000},
|
||||
{L14, 300 * 1000},
|
||||
{L15, 200 * 1000},
|
||||
{0, CPUFREQ_TABLE_END},
|
||||
{0, L0, 1700 * 1000},
|
||||
{0, L1, 1600 * 1000},
|
||||
{0, L2, 1500 * 1000},
|
||||
{0, L3, 1400 * 1000},
|
||||
{0, L4, 1300 * 1000},
|
||||
{0, L5, 1200 * 1000},
|
||||
{0, L6, 1100 * 1000},
|
||||
{0, L7, 1000 * 1000},
|
||||
{0, L8, 900 * 1000},
|
||||
{0, L9, 800 * 1000},
|
||||
{0, L10, 700 * 1000},
|
||||
{0, L11, 600 * 1000},
|
||||
{0, L12, 500 * 1000},
|
||||
{0, L13, 400 * 1000},
|
||||
{0, L14, 300 * 1000},
|
||||
{0, L15, 200 * 1000},
|
||||
{0, 0, CPUFREQ_TABLE_END},
|
||||
};
|
||||
|
||||
static struct apll_freq apll_freq_5250[] = {
|
||||
|
|
|
@ -33,11 +33,10 @@ int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
|
|||
continue;
|
||||
}
|
||||
if (!cpufreq_boost_enabled()
|
||||
&& table[i].driver_data == CPUFREQ_BOOST_FREQ)
|
||||
&& (table[i].flags & CPUFREQ_BOOST_FREQ))
|
||||
continue;
|
||||
|
||||
pr_debug("table entry %u: %u kHz, %u driver_data\n",
|
||||
i, freq, table[i].driver_data);
|
||||
pr_debug("table entry %u: %u kHz\n", i, freq);
|
||||
if (freq < min_freq)
|
||||
min_freq = freq;
|
||||
if (freq > max_freq)
|
||||
|
@ -175,8 +174,8 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
|
|||
} else
|
||||
*index = optimal.driver_data;
|
||||
|
||||
pr_debug("target is %u (%u kHz, %u)\n", *index, table[*index].frequency,
|
||||
table[*index].driver_data);
|
||||
pr_debug("target index is %u, freq is:%u kHz\n", *index,
|
||||
table[*index].frequency);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -230,7 +229,7 @@ static ssize_t show_available_freqs(struct cpufreq_policy *policy, char *buf,
|
|||
* show_boost = false and driver_data != BOOST freq
|
||||
* display NON BOOST freqs
|
||||
*/
|
||||
if (show_boost ^ (table[i].driver_data == CPUFREQ_BOOST_FREQ))
|
||||
if (show_boost ^ (table[i].flags & CPUFREQ_BOOST_FREQ))
|
||||
continue;
|
||||
|
||||
count += sprintf(&buf[count], "%d ", table[i].frequency);
|
||||
|
|
|
@ -254,7 +254,7 @@ acpi_cpufreq_cpu_init (
|
|||
}
|
||||
|
||||
/* alloc freq_table */
|
||||
data->freq_table = kmalloc(sizeof(*data->freq_table) *
|
||||
data->freq_table = kzalloc(sizeof(*data->freq_table) *
|
||||
(data->acpi_data.state_count + 1),
|
||||
GFP_KERNEL);
|
||||
if (!data->freq_table) {
|
||||
|
@ -275,7 +275,6 @@ acpi_cpufreq_cpu_init (
|
|||
/* table init */
|
||||
for (i = 0; i <= data->acpi_data.state_count; i++)
|
||||
{
|
||||
data->freq_table[i].driver_data = i;
|
||||
if (i < data->acpi_data.state_count) {
|
||||
data->freq_table[i].frequency =
|
||||
data->acpi_data.states[i].core_frequency * 1000;
|
||||
|
|
|
@ -43,9 +43,9 @@ static struct priv
|
|||
* table.
|
||||
*/
|
||||
static struct cpufreq_frequency_table kirkwood_freq_table[] = {
|
||||
{STATE_CPU_FREQ, 0}, /* CPU uses cpuclk */
|
||||
{STATE_DDR_FREQ, 0}, /* CPU uses ddrclk */
|
||||
{0, CPUFREQ_TABLE_END},
|
||||
{0, STATE_CPU_FREQ, 0}, /* CPU uses cpuclk */
|
||||
{0, STATE_DDR_FREQ, 0}, /* CPU uses ddrclk */
|
||||
{0, 0, CPUFREQ_TABLE_END},
|
||||
};
|
||||
|
||||
static unsigned int kirkwood_cpufreq_get_cpu_frequency(unsigned int cpu)
|
||||
|
|
|
@ -475,7 +475,7 @@ static int longhaul_get_ranges(void)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
longhaul_table = kmalloc((numscales + 1) * sizeof(*longhaul_table),
|
||||
longhaul_table = kzalloc((numscales + 1) * sizeof(*longhaul_table),
|
||||
GFP_KERNEL);
|
||||
if (!longhaul_table)
|
||||
return -ENOMEM;
|
||||
|
|
|
@ -69,7 +69,7 @@ static int loongson2_cpufreq_target(struct cpufreq_policy *policy,
|
|||
|
||||
static int loongson2_cpufreq_cpu_init(struct cpufreq_policy *policy)
|
||||
{
|
||||
static struct clk *cpuclk;
|
||||
struct clk *cpuclk;
|
||||
int i;
|
||||
unsigned long rate;
|
||||
int ret;
|
||||
|
|
|
@ -59,9 +59,9 @@
|
|||
#define CPUFREQ_LOW 1
|
||||
|
||||
static struct cpufreq_frequency_table maple_cpu_freqs[] = {
|
||||
{CPUFREQ_HIGH, 0},
|
||||
{CPUFREQ_LOW, 0},
|
||||
{0, CPUFREQ_TABLE_END},
|
||||
{0, CPUFREQ_HIGH, 0},
|
||||
{0, CPUFREQ_LOW, 0},
|
||||
{0, 0, CPUFREQ_TABLE_END},
|
||||
};
|
||||
|
||||
/* Power mode data is an array of the 32 bits PCR values to use for
|
||||
|
|
|
@ -92,16 +92,16 @@ static int cpufreq_p4_setdc(unsigned int cpu, unsigned int newstate)
|
|||
|
||||
|
||||
static struct cpufreq_frequency_table p4clockmod_table[] = {
|
||||
{DC_RESV, CPUFREQ_ENTRY_INVALID},
|
||||
{DC_DFLT, 0},
|
||||
{DC_25PT, 0},
|
||||
{DC_38PT, 0},
|
||||
{DC_50PT, 0},
|
||||
{DC_64PT, 0},
|
||||
{DC_75PT, 0},
|
||||
{DC_88PT, 0},
|
||||
{DC_DISABLE, 0},
|
||||
{DC_RESV, CPUFREQ_TABLE_END},
|
||||
{0, DC_RESV, CPUFREQ_ENTRY_INVALID},
|
||||
{0, DC_DFLT, 0},
|
||||
{0, DC_25PT, 0},
|
||||
{0, DC_38PT, 0},
|
||||
{0, DC_50PT, 0},
|
||||
{0, DC_64PT, 0},
|
||||
{0, DC_75PT, 0},
|
||||
{0, DC_88PT, 0},
|
||||
{0, DC_DISABLE, 0},
|
||||
{0, DC_RESV, CPUFREQ_TABLE_END},
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -60,12 +60,12 @@ static int current_astate;
|
|||
|
||||
/* We support 5(A0-A4) power states excluding turbo(A5-A6) modes */
|
||||
static struct cpufreq_frequency_table pas_freqs[] = {
|
||||
{0, 0},
|
||||
{1, 0},
|
||||
{2, 0},
|
||||
{3, 0},
|
||||
{4, 0},
|
||||
{0, CPUFREQ_TABLE_END},
|
||||
{0, 0, 0},
|
||||
{0, 1, 0},
|
||||
{0, 2, 0},
|
||||
{0, 3, 0},
|
||||
{0, 4, 0},
|
||||
{0, 0, CPUFREQ_TABLE_END},
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -81,9 +81,9 @@ static int is_pmu_based;
|
|||
#define CPUFREQ_LOW 1
|
||||
|
||||
static struct cpufreq_frequency_table pmac_cpu_freqs[] = {
|
||||
{CPUFREQ_HIGH, 0},
|
||||
{CPUFREQ_LOW, 0},
|
||||
{0, CPUFREQ_TABLE_END},
|
||||
{0, CPUFREQ_HIGH, 0},
|
||||
{0, CPUFREQ_LOW, 0},
|
||||
{0, 0, CPUFREQ_TABLE_END},
|
||||
};
|
||||
|
||||
static inline void local_delay(unsigned long ms)
|
||||
|
|
|
@ -65,9 +65,9 @@
|
|||
#define CPUFREQ_LOW 1
|
||||
|
||||
static struct cpufreq_frequency_table g5_cpu_freqs[] = {
|
||||
{CPUFREQ_HIGH, 0},
|
||||
{CPUFREQ_LOW, 0},
|
||||
{0, CPUFREQ_TABLE_END},
|
||||
{0, CPUFREQ_HIGH, 0},
|
||||
{0, CPUFREQ_LOW, 0},
|
||||
{0, 0, CPUFREQ_TABLE_END},
|
||||
};
|
||||
|
||||
/* Power mode data is an array of the 32 bits PCR values to use for
|
||||
|
|
|
@ -37,15 +37,15 @@ MODULE_PARM_DESC(bus_frequency, "Bus frequency in kHz");
|
|||
|
||||
/* Clock ratio multiplied by 10 - see table 27 in AMD#23446 */
|
||||
static struct cpufreq_frequency_table clock_ratio[] = {
|
||||
{60, /* 110 -> 6.0x */ 0},
|
||||
{55, /* 011 -> 5.5x */ 0},
|
||||
{50, /* 001 -> 5.0x */ 0},
|
||||
{45, /* 000 -> 4.5x */ 0},
|
||||
{40, /* 010 -> 4.0x */ 0},
|
||||
{35, /* 111 -> 3.5x */ 0},
|
||||
{30, /* 101 -> 3.0x */ 0},
|
||||
{20, /* 100 -> 2.0x */ 0},
|
||||
{0, CPUFREQ_TABLE_END}
|
||||
{0, 60, /* 110 -> 6.0x */ 0},
|
||||
{0, 55, /* 011 -> 5.5x */ 0},
|
||||
{0, 50, /* 001 -> 5.0x */ 0},
|
||||
{0, 45, /* 000 -> 4.5x */ 0},
|
||||
{0, 40, /* 010 -> 4.0x */ 0},
|
||||
{0, 35, /* 111 -> 3.5x */ 0},
|
||||
{0, 30, /* 101 -> 3.0x */ 0},
|
||||
{0, 20, /* 100 -> 2.0x */ 0},
|
||||
{0, 0, CPUFREQ_TABLE_END}
|
||||
};
|
||||
|
||||
static const u8 index_to_register[8] = { 6, 3, 1, 0, 2, 7, 5, 4 };
|
||||
|
|
|
@ -623,7 +623,7 @@ static int fill_powernow_table(struct powernow_k8_data *data,
|
|||
if (check_pst_table(data, pst, maxvid))
|
||||
return -EINVAL;
|
||||
|
||||
powernow_table = kmalloc((sizeof(*powernow_table)
|
||||
powernow_table = kzalloc((sizeof(*powernow_table)
|
||||
* (data->numps + 1)), GFP_KERNEL);
|
||||
if (!powernow_table) {
|
||||
printk(KERN_ERR PFX "powernow_table memory alloc failure\n");
|
||||
|
@ -793,7 +793,7 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
|
|||
}
|
||||
|
||||
/* fill in data->powernow_table */
|
||||
powernow_table = kmalloc((sizeof(*powernow_table)
|
||||
powernow_table = kzalloc((sizeof(*powernow_table)
|
||||
* (data->acpi_data.state_count + 1)), GFP_KERNEL);
|
||||
if (!powernow_table) {
|
||||
pr_debug("powernow_table memory alloc failure\n");
|
||||
|
@ -810,7 +810,6 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
|
|||
|
||||
powernow_table[data->acpi_data.state_count].frequency =
|
||||
CPUFREQ_TABLE_END;
|
||||
powernow_table[data->acpi_data.state_count].driver_data = 0;
|
||||
data->powernow_table = powernow_table;
|
||||
|
||||
if (cpumask_first(cpu_core_mask(data->cpu)) == data->cpu)
|
||||
|
|
|
@ -0,0 +1,341 @@
|
|||
/*
|
||||
* POWERNV cpufreq driver for the IBM POWER processors
|
||||
*
|
||||
* (C) Copyright IBM 2014
|
||||
*
|
||||
* Author: Vaidyanathan Srinivasan <svaidy at linux.vnet.ibm.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "powernv-cpufreq: " fmt
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/cpumask.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <asm/cputhreads.h>
|
||||
#include <asm/reg.h>
|
||||
|
||||
#define POWERNV_MAX_PSTATES 256
|
||||
|
||||
static struct cpufreq_frequency_table powernv_freqs[POWERNV_MAX_PSTATES+1];
|
||||
|
||||
/*
|
||||
* Note: The set of pstates consists of contiguous integers, the
|
||||
* smallest of which is indicated by powernv_pstate_info.min, the
|
||||
* largest of which is indicated by powernv_pstate_info.max.
|
||||
*
|
||||
* The nominal pstate is the highest non-turbo pstate in this
|
||||
* platform. This is indicated by powernv_pstate_info.nominal.
|
||||
*/
|
||||
static struct powernv_pstate_info {
|
||||
int min;
|
||||
int max;
|
||||
int nominal;
|
||||
int nr_pstates;
|
||||
} powernv_pstate_info;
|
||||
|
||||
/*
|
||||
* Initialize the freq table based on data obtained
|
||||
* from the firmware passed via device-tree
|
||||
*/
|
||||
static int init_powernv_pstates(void)
|
||||
{
|
||||
struct device_node *power_mgt;
|
||||
int i, pstate_min, pstate_max, pstate_nominal, nr_pstates = 0;
|
||||
const __be32 *pstate_ids, *pstate_freqs;
|
||||
u32 len_ids, len_freqs;
|
||||
|
||||
power_mgt = of_find_node_by_path("/ibm,opal/power-mgt");
|
||||
if (!power_mgt) {
|
||||
pr_warn("power-mgt node not found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (of_property_read_u32(power_mgt, "ibm,pstate-min", &pstate_min)) {
|
||||
pr_warn("ibm,pstate-min node not found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (of_property_read_u32(power_mgt, "ibm,pstate-max", &pstate_max)) {
|
||||
pr_warn("ibm,pstate-max node not found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (of_property_read_u32(power_mgt, "ibm,pstate-nominal",
|
||||
&pstate_nominal)) {
|
||||
pr_warn("ibm,pstate-nominal not found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
pr_info("cpufreq pstate min %d nominal %d max %d\n", pstate_min,
|
||||
pstate_nominal, pstate_max);
|
||||
|
||||
pstate_ids = of_get_property(power_mgt, "ibm,pstate-ids", &len_ids);
|
||||
if (!pstate_ids) {
|
||||
pr_warn("ibm,pstate-ids not found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
pstate_freqs = of_get_property(power_mgt, "ibm,pstate-frequencies-mhz",
|
||||
&len_freqs);
|
||||
if (!pstate_freqs) {
|
||||
pr_warn("ibm,pstate-frequencies-mhz not found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
WARN_ON(len_ids != len_freqs);
|
||||
nr_pstates = min(len_ids, len_freqs) / sizeof(u32);
|
||||
if (!nr_pstates) {
|
||||
pr_warn("No PStates found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
pr_debug("NR PStates %d\n", nr_pstates);
|
||||
for (i = 0; i < nr_pstates; i++) {
|
||||
u32 id = be32_to_cpu(pstate_ids[i]);
|
||||
u32 freq = be32_to_cpu(pstate_freqs[i]);
|
||||
|
||||
pr_debug("PState id %d freq %d MHz\n", id, freq);
|
||||
powernv_freqs[i].frequency = freq * 1000; /* kHz */
|
||||
powernv_freqs[i].driver_data = id;
|
||||
}
|
||||
/* End of list marker entry */
|
||||
powernv_freqs[i].frequency = CPUFREQ_TABLE_END;
|
||||
|
||||
powernv_pstate_info.min = pstate_min;
|
||||
powernv_pstate_info.max = pstate_max;
|
||||
powernv_pstate_info.nominal = pstate_nominal;
|
||||
powernv_pstate_info.nr_pstates = nr_pstates;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Returns the CPU frequency corresponding to the pstate_id. */
|
||||
static unsigned int pstate_id_to_freq(int pstate_id)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = powernv_pstate_info.max - pstate_id;
|
||||
BUG_ON(i >= powernv_pstate_info.nr_pstates || i < 0);
|
||||
|
||||
return powernv_freqs[i].frequency;
|
||||
}
|
||||
|
||||
/*
|
||||
* cpuinfo_nominal_freq_show - Show the nominal CPU frequency as indicated by
|
||||
* the firmware
|
||||
*/
|
||||
static ssize_t cpuinfo_nominal_freq_show(struct cpufreq_policy *policy,
|
||||
char *buf)
|
||||
{
|
||||
return sprintf(buf, "%u\n",
|
||||
pstate_id_to_freq(powernv_pstate_info.nominal));
|
||||
}
|
||||
|
||||
struct freq_attr cpufreq_freq_attr_cpuinfo_nominal_freq =
|
||||
__ATTR_RO(cpuinfo_nominal_freq);
|
||||
|
||||
static struct freq_attr *powernv_cpu_freq_attr[] = {
|
||||
&cpufreq_freq_attr_scaling_available_freqs,
|
||||
&cpufreq_freq_attr_cpuinfo_nominal_freq,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/* Helper routines */
|
||||
|
||||
/* Access helpers to power mgt SPR */
|
||||
|
||||
static inline unsigned long get_pmspr(unsigned long sprn)
|
||||
{
|
||||
switch (sprn) {
|
||||
case SPRN_PMCR:
|
||||
return mfspr(SPRN_PMCR);
|
||||
|
||||
case SPRN_PMICR:
|
||||
return mfspr(SPRN_PMICR);
|
||||
|
||||
case SPRN_PMSR:
|
||||
return mfspr(SPRN_PMSR);
|
||||
}
|
||||
BUG();
|
||||
}
|
||||
|
||||
static inline void set_pmspr(unsigned long sprn, unsigned long val)
|
||||
{
|
||||
switch (sprn) {
|
||||
case SPRN_PMCR:
|
||||
mtspr(SPRN_PMCR, val);
|
||||
return;
|
||||
|
||||
case SPRN_PMICR:
|
||||
mtspr(SPRN_PMICR, val);
|
||||
return;
|
||||
}
|
||||
BUG();
|
||||
}
|
||||
|
||||
/*
|
||||
* Use objects of this type to query/update
|
||||
* pstates on a remote CPU via smp_call_function.
|
||||
*/
|
||||
struct powernv_smp_call_data {
|
||||
unsigned int freq;
|
||||
int pstate_id;
|
||||
};
|
||||
|
||||
/*
|
||||
* powernv_read_cpu_freq: Reads the current frequency on this CPU.
|
||||
*
|
||||
* Called via smp_call_function.
|
||||
*
|
||||
* Note: The caller of the smp_call_function should pass an argument of
|
||||
* the type 'struct powernv_smp_call_data *' along with this function.
|
||||
*
|
||||
* The current frequency on this CPU will be returned via
|
||||
* ((struct powernv_smp_call_data *)arg)->freq;
|
||||
*/
|
||||
static void powernv_read_cpu_freq(void *arg)
|
||||
{
|
||||
unsigned long pmspr_val;
|
||||
s8 local_pstate_id;
|
||||
struct powernv_smp_call_data *freq_data = arg;
|
||||
|
||||
pmspr_val = get_pmspr(SPRN_PMSR);
|
||||
|
||||
/*
|
||||
* The local pstate id corresponds bits 48..55 in the PMSR.
|
||||
* Note: Watch out for the sign!
|
||||
*/
|
||||
local_pstate_id = (pmspr_val >> 48) & 0xFF;
|
||||
freq_data->pstate_id = local_pstate_id;
|
||||
freq_data->freq = pstate_id_to_freq(freq_data->pstate_id);
|
||||
|
||||
pr_debug("cpu %d pmsr %016lX pstate_id %d frequency %d kHz\n",
|
||||
raw_smp_processor_id(), pmspr_val, freq_data->pstate_id,
|
||||
freq_data->freq);
|
||||
}
|
||||
|
||||
/*
|
||||
* powernv_cpufreq_get: Returns the CPU frequency as reported by the
|
||||
* firmware for CPU 'cpu'. This value is reported through the sysfs
|
||||
* file cpuinfo_cur_freq.
|
||||
*/
|
||||
unsigned int powernv_cpufreq_get(unsigned int cpu)
|
||||
{
|
||||
struct powernv_smp_call_data freq_data;
|
||||
|
||||
smp_call_function_any(cpu_sibling_mask(cpu), powernv_read_cpu_freq,
|
||||
&freq_data, 1);
|
||||
|
||||
return freq_data.freq;
|
||||
}
|
||||
|
||||
/*
|
||||
* set_pstate: Sets the pstate on this CPU.
|
||||
*
|
||||
* This is called via an smp_call_function.
|
||||
*
|
||||
* The caller must ensure that freq_data is of the type
|
||||
* (struct powernv_smp_call_data *) and the pstate_id which needs to be set
|
||||
* on this CPU should be present in freq_data->pstate_id.
|
||||
*/
|
||||
static void set_pstate(void *freq_data)
|
||||
{
|
||||
unsigned long val;
|
||||
unsigned long pstate_ul =
|
||||
((struct powernv_smp_call_data *) freq_data)->pstate_id;
|
||||
|
||||
val = get_pmspr(SPRN_PMCR);
|
||||
val = val & 0x0000FFFFFFFFFFFFULL;
|
||||
|
||||
pstate_ul = pstate_ul & 0xFF;
|
||||
|
||||
/* Set both global(bits 56..63) and local(bits 48..55) PStates */
|
||||
val = val | (pstate_ul << 56) | (pstate_ul << 48);
|
||||
|
||||
pr_debug("Setting cpu %d pmcr to %016lX\n",
|
||||
raw_smp_processor_id(), val);
|
||||
set_pmspr(SPRN_PMCR, val);
|
||||
}
|
||||
|
||||
/*
|
||||
* powernv_cpufreq_target_index: Sets the frequency corresponding to
|
||||
* the cpufreq table entry indexed by new_index on the cpus in the
|
||||
* mask policy->cpus
|
||||
*/
|
||||
static int powernv_cpufreq_target_index(struct cpufreq_policy *policy,
|
||||
unsigned int new_index)
|
||||
{
|
||||
struct powernv_smp_call_data freq_data;
|
||||
|
||||
freq_data.pstate_id = powernv_freqs[new_index].driver_data;
|
||||
|
||||
/*
|
||||
* Use smp_call_function to send IPI and execute the
|
||||
* mtspr on target CPU. We could do that without IPI
|
||||
* if current CPU is within policy->cpus (core)
|
||||
*/
|
||||
smp_call_function_any(policy->cpus, set_pstate, &freq_data, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int powernv_cpufreq_cpu_init(struct cpufreq_policy *policy)
|
||||
{
|
||||
int base, i;
|
||||
|
||||
base = cpu_first_thread_sibling(policy->cpu);
|
||||
|
||||
for (i = 0; i < threads_per_core; i++)
|
||||
cpumask_set_cpu(base + i, policy->cpus);
|
||||
|
||||
return cpufreq_table_validate_and_show(policy, powernv_freqs);
|
||||
}
|
||||
|
||||
static struct cpufreq_driver powernv_cpufreq_driver = {
|
||||
.name = "powernv-cpufreq",
|
||||
.flags = CPUFREQ_CONST_LOOPS,
|
||||
.init = powernv_cpufreq_cpu_init,
|
||||
.verify = cpufreq_generic_frequency_table_verify,
|
||||
.target_index = powernv_cpufreq_target_index,
|
||||
.get = powernv_cpufreq_get,
|
||||
.attr = powernv_cpu_freq_attr,
|
||||
};
|
||||
|
||||
static int __init powernv_cpufreq_init(void)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
/* Discover pstates from device tree and init */
|
||||
rc = init_powernv_pstates();
|
||||
if (rc) {
|
||||
pr_info("powernv-cpufreq disabled. System does not support PState control\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
return cpufreq_register_driver(&powernv_cpufreq_driver);
|
||||
}
|
||||
module_init(powernv_cpufreq_init);
|
||||
|
||||
static void __exit powernv_cpufreq_exit(void)
|
||||
{
|
||||
cpufreq_unregister_driver(&powernv_cpufreq_driver);
|
||||
}
|
||||
module_exit(powernv_cpufreq_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Vaidyanathan Srinivasan <svaidy at linux.vnet.ibm.com>");
|
|
@ -13,7 +13,6 @@
|
|||
#include <linux/clk.h>
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/errno.h>
|
||||
#include <sysdev/fsl_soc.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
|
|
|
@ -32,15 +32,15 @@
|
|||
|
||||
/* the CBE supports an 8 step frequency scaling */
|
||||
static struct cpufreq_frequency_table cbe_freqs[] = {
|
||||
{1, 0},
|
||||
{2, 0},
|
||||
{3, 0},
|
||||
{4, 0},
|
||||
{5, 0},
|
||||
{6, 0},
|
||||
{8, 0},
|
||||
{10, 0},
|
||||
{0, CPUFREQ_TABLE_END},
|
||||
{0, 1, 0},
|
||||
{0, 2, 0},
|
||||
{0, 3, 0},
|
||||
{0, 4, 0},
|
||||
{0, 5, 0},
|
||||
{0, 6, 0},
|
||||
{0, 8, 0},
|
||||
{0, 10, 0},
|
||||
{0, 0, CPUFREQ_TABLE_END},
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -72,19 +72,19 @@ static struct s3c2416_dvfs s3c2416_dvfs_table[] = {
|
|||
#endif
|
||||
|
||||
static struct cpufreq_frequency_table s3c2416_freq_table[] = {
|
||||
{ SOURCE_HCLK, FREQ_DVS },
|
||||
{ SOURCE_ARMDIV, 133333 },
|
||||
{ SOURCE_ARMDIV, 266666 },
|
||||
{ SOURCE_ARMDIV, 400000 },
|
||||
{ 0, CPUFREQ_TABLE_END },
|
||||
{ 0, SOURCE_HCLK, FREQ_DVS },
|
||||
{ 0, SOURCE_ARMDIV, 133333 },
|
||||
{ 0, SOURCE_ARMDIV, 266666 },
|
||||
{ 0, SOURCE_ARMDIV, 400000 },
|
||||
{ 0, 0, CPUFREQ_TABLE_END },
|
||||
};
|
||||
|
||||
static struct cpufreq_frequency_table s3c2450_freq_table[] = {
|
||||
{ SOURCE_HCLK, FREQ_DVS },
|
||||
{ SOURCE_ARMDIV, 133500 },
|
||||
{ SOURCE_ARMDIV, 267000 },
|
||||
{ SOURCE_ARMDIV, 534000 },
|
||||
{ 0, CPUFREQ_TABLE_END },
|
||||
{ 0, SOURCE_HCLK, FREQ_DVS },
|
||||
{ 0, SOURCE_ARMDIV, 133500 },
|
||||
{ 0, SOURCE_ARMDIV, 267000 },
|
||||
{ 0, SOURCE_ARMDIV, 534000 },
|
||||
{ 0, 0, CPUFREQ_TABLE_END },
|
||||
};
|
||||
|
||||
static unsigned int s3c2416_cpufreq_get_speed(unsigned int cpu)
|
||||
|
|
|
@ -586,7 +586,7 @@ static int s3c_cpufreq_build_freq(void)
|
|||
size = cpu_cur.info->calc_freqtable(&cpu_cur, NULL, 0);
|
||||
size++;
|
||||
|
||||
ftab = kmalloc(sizeof(*ftab) * size, GFP_KERNEL);
|
||||
ftab = kzalloc(sizeof(*ftab) * size, GFP_KERNEL);
|
||||
if (!ftab) {
|
||||
printk(KERN_ERR "%s: no memory for tables\n", __func__);
|
||||
return -ENOMEM;
|
||||
|
@ -664,7 +664,7 @@ int __init s3c_plltab_register(struct cpufreq_frequency_table *plls,
|
|||
|
||||
size = sizeof(*vals) * (plls_no + 1);
|
||||
|
||||
vals = kmalloc(size, GFP_KERNEL);
|
||||
vals = kzalloc(size, GFP_KERNEL);
|
||||
if (vals) {
|
||||
memcpy(vals, plls, size);
|
||||
pll_reg = vals;
|
||||
|
|
|
@ -37,19 +37,19 @@ static struct s3c64xx_dvfs s3c64xx_dvfs_table[] = {
|
|||
};
|
||||
|
||||
static struct cpufreq_frequency_table s3c64xx_freq_table[] = {
|
||||
{ 0, 66000 },
|
||||
{ 0, 100000 },
|
||||
{ 0, 133000 },
|
||||
{ 1, 200000 },
|
||||
{ 1, 222000 },
|
||||
{ 1, 266000 },
|
||||
{ 2, 333000 },
|
||||
{ 2, 400000 },
|
||||
{ 2, 532000 },
|
||||
{ 2, 533000 },
|
||||
{ 3, 667000 },
|
||||
{ 4, 800000 },
|
||||
{ 0, CPUFREQ_TABLE_END },
|
||||
{ 0, 0, 66000 },
|
||||
{ 0, 0, 100000 },
|
||||
{ 0, 0, 133000 },
|
||||
{ 0, 1, 200000 },
|
||||
{ 0, 1, 222000 },
|
||||
{ 0, 1, 266000 },
|
||||
{ 0, 2, 333000 },
|
||||
{ 0, 2, 400000 },
|
||||
{ 0, 2, 532000 },
|
||||
{ 0, 2, 533000 },
|
||||
{ 0, 3, 667000 },
|
||||
{ 0, 4, 800000 },
|
||||
{ 0, 0, CPUFREQ_TABLE_END },
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
|
@ -64,12 +64,12 @@ enum s5pv210_dmc_port {
|
|||
};
|
||||
|
||||
static struct cpufreq_frequency_table s5pv210_freq_table[] = {
|
||||
{L0, 1000*1000},
|
||||
{L1, 800*1000},
|
||||
{L2, 400*1000},
|
||||
{L3, 200*1000},
|
||||
{L4, 100*1000},
|
||||
{0, CPUFREQ_TABLE_END},
|
||||
{0, L0, 1000*1000},
|
||||
{0, L1, 800*1000},
|
||||
{0, L2, 400*1000},
|
||||
{0, L3, 200*1000},
|
||||
{0, L4, 100*1000},
|
||||
{0, 0, CPUFREQ_TABLE_END},
|
||||
};
|
||||
|
||||
static struct regulator *arm_regulator;
|
||||
|
|
|
@ -33,9 +33,9 @@ static __u8 __iomem *cpuctl;
|
|||
#define PFX "sc520_freq: "
|
||||
|
||||
static struct cpufreq_frequency_table sc520_freq_table[] = {
|
||||
{0x01, 100000},
|
||||
{0x02, 133000},
|
||||
{0, CPUFREQ_TABLE_END},
|
||||
{0, 0x01, 100000},
|
||||
{0, 0x02, 133000},
|
||||
{0, 0, CPUFREQ_TABLE_END},
|
||||
};
|
||||
|
||||
static unsigned int sc520_freq_get_cpu_frequency(unsigned int cpu)
|
||||
|
|
|
@ -195,18 +195,15 @@ static int spear_cpufreq_probe(struct platform_device *pdev)
|
|||
cnt = prop->length / sizeof(u32);
|
||||
val = prop->value;
|
||||
|
||||
freq_tbl = kmalloc(sizeof(*freq_tbl) * (cnt + 1), GFP_KERNEL);
|
||||
freq_tbl = kzalloc(sizeof(*freq_tbl) * (cnt + 1), GFP_KERNEL);
|
||||
if (!freq_tbl) {
|
||||
ret = -ENOMEM;
|
||||
goto out_put_node;
|
||||
}
|
||||
|
||||
for (i = 0; i < cnt; i++) {
|
||||
freq_tbl[i].driver_data = i;
|
||||
for (i = 0; i < cnt; i++)
|
||||
freq_tbl[i].frequency = be32_to_cpup(val++);
|
||||
}
|
||||
|
||||
freq_tbl[i].driver_data = i;
|
||||
freq_tbl[i].frequency = CPUFREQ_TABLE_END;
|
||||
|
||||
spear_cpufreq.freq_tbl = freq_tbl;
|
||||
|
|
|
@ -49,9 +49,9 @@ static u32 pmbase;
|
|||
* are in kHz for the time being.
|
||||
*/
|
||||
static struct cpufreq_frequency_table speedstep_freqs[] = {
|
||||
{SPEEDSTEP_HIGH, 0},
|
||||
{SPEEDSTEP_LOW, 0},
|
||||
{0, CPUFREQ_TABLE_END},
|
||||
{0, SPEEDSTEP_HIGH, 0},
|
||||
{0, SPEEDSTEP_LOW, 0},
|
||||
{0, 0, CPUFREQ_TABLE_END},
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -42,9 +42,9 @@ static enum speedstep_processor speedstep_processor;
|
|||
* are in kHz for the time being.
|
||||
*/
|
||||
static struct cpufreq_frequency_table speedstep_freqs[] = {
|
||||
{SPEEDSTEP_HIGH, 0},
|
||||
{SPEEDSTEP_LOW, 0},
|
||||
{0, CPUFREQ_TABLE_END},
|
||||
{0, SPEEDSTEP_HIGH, 0},
|
||||
{0, SPEEDSTEP_LOW, 0},
|
||||
{0, 0, CPUFREQ_TABLE_END},
|
||||
};
|
||||
|
||||
#define GET_SPEEDSTEP_OWNER 0
|
||||
|
|
|
@ -45,7 +45,7 @@ static int ucv2_target(struct cpufreq_policy *policy,
|
|||
freqs.new = target_freq;
|
||||
|
||||
cpufreq_freq_transition_begin(policy, &freqs);
|
||||
ret = clk_set_rate(policy->mclk, target_freq * 1000);
|
||||
ret = clk_set_rate(policy->clk, target_freq * 1000);
|
||||
cpufreq_freq_transition_end(policy, &freqs, ret);
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -293,6 +293,7 @@ static ssize_t show_state_##_name(struct cpuidle_state *state, \
|
|||
}
|
||||
|
||||
define_show_state_function(exit_latency)
|
||||
define_show_state_function(target_residency)
|
||||
define_show_state_function(power_usage)
|
||||
define_show_state_ull_function(usage)
|
||||
define_show_state_ull_function(time)
|
||||
|
@ -304,6 +305,7 @@ define_store_state_ull_function(disable)
|
|||
define_one_state_ro(name, show_state_name);
|
||||
define_one_state_ro(desc, show_state_desc);
|
||||
define_one_state_ro(latency, show_state_exit_latency);
|
||||
define_one_state_ro(residency, show_state_target_residency);
|
||||
define_one_state_ro(power, show_state_power_usage);
|
||||
define_one_state_ro(usage, show_state_usage);
|
||||
define_one_state_ro(time, show_state_time);
|
||||
|
@ -313,6 +315,7 @@ static struct attribute *cpuidle_state_default_attrs[] = {
|
|||
&attr_name.attr,
|
||||
&attr_desc.attr,
|
||||
&attr_latency.attr,
|
||||
&attr_residency.attr,
|
||||
&attr_power.attr,
|
||||
&attr_usage.attr,
|
||||
&attr_time.attr,
|
||||
|
|
|
@ -196,6 +196,53 @@ static struct cpuidle_state snb_cstates[] = {
|
|||
.enter = NULL }
|
||||
};
|
||||
|
||||
static struct cpuidle_state byt_cstates[] = {
|
||||
{
|
||||
.name = "C1-BYT",
|
||||
.desc = "MWAIT 0x00",
|
||||
.flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_TIME_VALID,
|
||||
.exit_latency = 1,
|
||||
.target_residency = 1,
|
||||
.enter = &intel_idle },
|
||||
{
|
||||
.name = "C1E-BYT",
|
||||
.desc = "MWAIT 0x01",
|
||||
.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_TIME_VALID,
|
||||
.exit_latency = 15,
|
||||
.target_residency = 30,
|
||||
.enter = &intel_idle },
|
||||
{
|
||||
.name = "C6N-BYT",
|
||||
.desc = "MWAIT 0x58",
|
||||
.flags = MWAIT2flg(0x58) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
|
||||
.exit_latency = 40,
|
||||
.target_residency = 275,
|
||||
.enter = &intel_idle },
|
||||
{
|
||||
.name = "C6S-BYT",
|
||||
.desc = "MWAIT 0x52",
|
||||
.flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
|
||||
.exit_latency = 140,
|
||||
.target_residency = 560,
|
||||
.enter = &intel_idle },
|
||||
{
|
||||
.name = "C7-BYT",
|
||||
.desc = "MWAIT 0x60",
|
||||
.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
|
||||
.exit_latency = 1200,
|
||||
.target_residency = 1500,
|
||||
.enter = &intel_idle },
|
||||
{
|
||||
.name = "C7S-BYT",
|
||||
.desc = "MWAIT 0x64",
|
||||
.flags = MWAIT2flg(0x64) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
|
||||
.exit_latency = 10000,
|
||||
.target_residency = 20000,
|
||||
.enter = &intel_idle },
|
||||
{
|
||||
.enter = NULL }
|
||||
};
|
||||
|
||||
static struct cpuidle_state ivb_cstates[] = {
|
||||
{
|
||||
.name = "C1-IVB",
|
||||
|
@ -236,6 +283,105 @@ static struct cpuidle_state ivb_cstates[] = {
|
|||
.enter = NULL }
|
||||
};
|
||||
|
||||
static struct cpuidle_state ivt_cstates[] = {
|
||||
{
|
||||
.name = "C1-IVT",
|
||||
.desc = "MWAIT 0x00",
|
||||
.flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_TIME_VALID,
|
||||
.exit_latency = 1,
|
||||
.target_residency = 1,
|
||||
.enter = &intel_idle },
|
||||
{
|
||||
.name = "C1E-IVT",
|
||||
.desc = "MWAIT 0x01",
|
||||
.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_TIME_VALID,
|
||||
.exit_latency = 10,
|
||||
.target_residency = 80,
|
||||
.enter = &intel_idle },
|
||||
{
|
||||
.name = "C3-IVT",
|
||||
.desc = "MWAIT 0x10",
|
||||
.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
|
||||
.exit_latency = 59,
|
||||
.target_residency = 156,
|
||||
.enter = &intel_idle },
|
||||
{
|
||||
.name = "C6-IVT",
|
||||
.desc = "MWAIT 0x20",
|
||||
.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
|
||||
.exit_latency = 82,
|
||||
.target_residency = 300,
|
||||
.enter = &intel_idle },
|
||||
{
|
||||
.enter = NULL }
|
||||
};
|
||||
|
||||
static struct cpuidle_state ivt_cstates_4s[] = {
|
||||
{
|
||||
.name = "C1-IVT-4S",
|
||||
.desc = "MWAIT 0x00",
|
||||
.flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_TIME_VALID,
|
||||
.exit_latency = 1,
|
||||
.target_residency = 1,
|
||||
.enter = &intel_idle },
|
||||
{
|
||||
.name = "C1E-IVT-4S",
|
||||
.desc = "MWAIT 0x01",
|
||||
.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_TIME_VALID,
|
||||
.exit_latency = 10,
|
||||
.target_residency = 250,
|
||||
.enter = &intel_idle },
|
||||
{
|
||||
.name = "C3-IVT-4S",
|
||||
.desc = "MWAIT 0x10",
|
||||
.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
|
||||
.exit_latency = 59,
|
||||
.target_residency = 300,
|
||||
.enter = &intel_idle },
|
||||
{
|
||||
.name = "C6-IVT-4S",
|
||||
.desc = "MWAIT 0x20",
|
||||
.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
|
||||
.exit_latency = 84,
|
||||
.target_residency = 400,
|
||||
.enter = &intel_idle },
|
||||
{
|
||||
.enter = NULL }
|
||||
};
|
||||
|
||||
static struct cpuidle_state ivt_cstates_8s[] = {
|
||||
{
|
||||
.name = "C1-IVT-8S",
|
||||
.desc = "MWAIT 0x00",
|
||||
.flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_TIME_VALID,
|
||||
.exit_latency = 1,
|
||||
.target_residency = 1,
|
||||
.enter = &intel_idle },
|
||||
{
|
||||
.name = "C1E-IVT-8S",
|
||||
.desc = "MWAIT 0x01",
|
||||
.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_TIME_VALID,
|
||||
.exit_latency = 10,
|
||||
.target_residency = 500,
|
||||
.enter = &intel_idle },
|
||||
{
|
||||
.name = "C3-IVT-8S",
|
||||
.desc = "MWAIT 0x10",
|
||||
.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
|
||||
.exit_latency = 59,
|
||||
.target_residency = 600,
|
||||
.enter = &intel_idle },
|
||||
{
|
||||
.name = "C6-IVT-8S",
|
||||
.desc = "MWAIT 0x20",
|
||||
.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
|
||||
.exit_latency = 88,
|
||||
.target_residency = 700,
|
||||
.enter = &intel_idle },
|
||||
{
|
||||
.enter = NULL }
|
||||
};
|
||||
|
||||
static struct cpuidle_state hsw_cstates[] = {
|
||||
{
|
||||
.name = "C1-HSW",
|
||||
|
@ -464,11 +610,21 @@ static const struct idle_cpu idle_cpu_snb = {
|
|||
.disable_promotion_to_c1e = true,
|
||||
};
|
||||
|
||||
static const struct idle_cpu idle_cpu_byt = {
|
||||
.state_table = byt_cstates,
|
||||
.disable_promotion_to_c1e = true,
|
||||
};
|
||||
|
||||
static const struct idle_cpu idle_cpu_ivb = {
|
||||
.state_table = ivb_cstates,
|
||||
.disable_promotion_to_c1e = true,
|
||||
};
|
||||
|
||||
static const struct idle_cpu idle_cpu_ivt = {
|
||||
.state_table = ivt_cstates,
|
||||
.disable_promotion_to_c1e = true,
|
||||
};
|
||||
|
||||
static const struct idle_cpu idle_cpu_hsw = {
|
||||
.state_table = hsw_cstates,
|
||||
.disable_promotion_to_c1e = true,
|
||||
|
@ -494,8 +650,10 @@ static const struct x86_cpu_id intel_idle_ids[] = {
|
|||
ICPU(0x2f, idle_cpu_nehalem),
|
||||
ICPU(0x2a, idle_cpu_snb),
|
||||
ICPU(0x2d, idle_cpu_snb),
|
||||
ICPU(0x36, idle_cpu_atom),
|
||||
ICPU(0x37, idle_cpu_byt),
|
||||
ICPU(0x3a, idle_cpu_ivb),
|
||||
ICPU(0x3e, idle_cpu_ivb),
|
||||
ICPU(0x3e, idle_cpu_ivt),
|
||||
ICPU(0x3c, idle_cpu_hsw),
|
||||
ICPU(0x3f, idle_cpu_hsw),
|
||||
ICPU(0x45, idle_cpu_hsw),
|
||||
|
@ -572,6 +730,39 @@ static void intel_idle_cpuidle_devices_uninit(void)
|
|||
free_percpu(intel_idle_cpuidle_devices);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* intel_idle_state_table_update()
|
||||
*
|
||||
* Update the default state_table for this CPU-id
|
||||
*
|
||||
* Currently used to access tuned IVT multi-socket targets
|
||||
* Assumption: num_sockets == (max_package_num + 1)
|
||||
*/
|
||||
void intel_idle_state_table_update(void)
|
||||
{
|
||||
/* IVT uses a different table for 1-2, 3-4, and > 4 sockets */
|
||||
if (boot_cpu_data.x86_model == 0x3e) { /* IVT */
|
||||
int cpu, package_num, num_sockets = 1;
|
||||
|
||||
for_each_online_cpu(cpu) {
|
||||
package_num = topology_physical_package_id(cpu);
|
||||
if (package_num + 1 > num_sockets) {
|
||||
num_sockets = package_num + 1;
|
||||
|
||||
if (num_sockets > 4)
|
||||
cpuidle_state_table = ivt_cstates_8s;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (num_sockets > 2)
|
||||
cpuidle_state_table = ivt_cstates_4s;
|
||||
/* else, 1 and 2 socket systems use default ivt_cstates */
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* intel_idle_cpuidle_driver_init()
|
||||
* allocate, initialize cpuidle_states
|
||||
|
@ -581,10 +772,12 @@ static int __init intel_idle_cpuidle_driver_init(void)
|
|||
int cstate;
|
||||
struct cpuidle_driver *drv = &intel_idle_driver;
|
||||
|
||||
intel_idle_state_table_update();
|
||||
|
||||
drv->state_count = 1;
|
||||
|
||||
for (cstate = 0; cstate < CPUIDLE_STATE_MAX; ++cstate) {
|
||||
int num_substates, mwait_hint, mwait_cstate, mwait_substate;
|
||||
int num_substates, mwait_hint, mwait_cstate;
|
||||
|
||||
if (cpuidle_state_table[cstate].enter == NULL)
|
||||
break;
|
||||
|
@ -597,14 +790,13 @@ static int __init intel_idle_cpuidle_driver_init(void)
|
|||
|
||||
mwait_hint = flg2MWAIT(cpuidle_state_table[cstate].flags);
|
||||
mwait_cstate = MWAIT_HINT2CSTATE(mwait_hint);
|
||||
mwait_substate = MWAIT_HINT2SUBSTATE(mwait_hint);
|
||||
|
||||
/* does the state exist in CPUID.MWAIT? */
|
||||
/* number of sub-states for this state in CPUID.MWAIT */
|
||||
num_substates = (mwait_substates >> ((mwait_cstate + 1) * 4))
|
||||
& MWAIT_SUBSTATE_MASK;
|
||||
|
||||
/* if sub-state in table is not enumerated by CPUID */
|
||||
if ((mwait_substate + 1) > num_substates)
|
||||
/* if NO sub-states for this state in CPUID, skip it */
|
||||
if (num_substates == 0)
|
||||
continue;
|
||||
|
||||
if (((mwait_cstate + 1) > 2) &&
|
||||
|
|
|
@ -455,11 +455,14 @@ extern struct cpufreq_governor cpufreq_gov_conservative;
|
|||
* FREQUENCY TABLE HELPERS *
|
||||
*********************************************************************/
|
||||
|
||||
#define CPUFREQ_ENTRY_INVALID ~0
|
||||
#define CPUFREQ_TABLE_END ~1
|
||||
#define CPUFREQ_BOOST_FREQ ~2
|
||||
/* Special Values of .frequency field */
|
||||
#define CPUFREQ_ENTRY_INVALID ~0
|
||||
#define CPUFREQ_TABLE_END ~1
|
||||
/* Special Values of .flags field */
|
||||
#define CPUFREQ_BOOST_FREQ (1 << 0)
|
||||
|
||||
struct cpufreq_frequency_table {
|
||||
unsigned int flags;
|
||||
unsigned int driver_data; /* driver specific data, not used by core */
|
||||
unsigned int frequency; /* kHz - doesn't need to be in ascending
|
||||
* order */
|
||||
|
|
|
@ -47,21 +47,22 @@ displays the statistics gathered since it was forked.
|
|||
.PP
|
||||
.SH FIELD DESCRIPTIONS
|
||||
.nf
|
||||
\fBpk\fP processor package number.
|
||||
\fBcor\fP processor core number.
|
||||
\fBPackage\fP processor package number.
|
||||
\fBCore\fP processor core number.
|
||||
\fBCPU\fP Linux CPU (logical processor) number.
|
||||
Note that multiple CPUs per core indicate support for Intel(R) Hyper-Threading Technology.
|
||||
\fB%c0\fP percent of the interval that the CPU retired instructions.
|
||||
\fBGHz\fP average clock rate while the CPU was in c0 state.
|
||||
\fBTSC\fP average GHz that the TSC ran during the entire interval.
|
||||
\fB%c1, %c3, %c6, %c7\fP show the percentage residency in hardware core idle states.
|
||||
\fBCTMP\fP Degrees Celsius reported by the per-core Digital Thermal Sensor.
|
||||
\fBPTMP\fP Degrees Celsius reported by the per-package Package Thermal Monitor.
|
||||
\fB%pc2, %pc3, %pc6, %pc7\fP percentage residency in hardware package idle states.
|
||||
\fBPkg_W\fP Watts consumed by the whole package.
|
||||
\fBCor_W\fP Watts consumed by the core part of the package.
|
||||
\fBGFX_W\fP Watts consumed by the Graphics part of the package -- available only on client processors.
|
||||
\fBRAM_W\fP Watts consumed by the DRAM DIMMS -- available only on server processors.
|
||||
\fBAVG_MHz\fP number of cycles executed divided by time elapsed.
|
||||
\fB%Buzy\fP percent of the interval that the CPU retired instructions, aka. % of time in "C0" state.
|
||||
\fBBzy_MHz\fP average clock rate while the CPU was busy (in "c0" state).
|
||||
\fBTSC_MHz\fP average MHz that the TSC ran during the entire interval.
|
||||
\fBCPU%c1, CPU%c3, CPU%c6, CPU%c7\fP show the percentage residency in hardware core idle states.
|
||||
\fBCoreTmp\fP Degrees Celsius reported by the per-core Digital Thermal Sensor.
|
||||
\fBPkgTtmp\fP Degrees Celsius reported by the per-package Package Thermal Monitor.
|
||||
\fBPkg%pc2, Pkg%pc3, Pkg%pc6, Pkg%pc7\fP percentage residency in hardware package idle states.
|
||||
\fBPkgWatt\fP Watts consumed by the whole package.
|
||||
\fBCorWatt\fP Watts consumed by the core part of the package.
|
||||
\fBGFXWatt\fP Watts consumed by the Graphics part of the package -- available only on client processors.
|
||||
\fBRAMWatt\fP Watts consumed by the DRAM DIMMS -- available only on server processors.
|
||||
\fBPKG_%\fP percent of the interval that RAPL throttling was active on the Package.
|
||||
\fBRAM_%\fP percent of the interval that RAPL throttling was active on DRAM.
|
||||
.fi
|
||||
|
@ -78,29 +79,17 @@ For Watts columns, the summary is a system total.
|
|||
Subsequent rows show per-CPU statistics.
|
||||
|
||||
.nf
|
||||
[root@sandy]# ./turbostat
|
||||
cor CPU %c0 GHz TSC %c1 %c3 %c6 %c7 CTMP PTMP %pc2 %pc3 %pc6 %pc7 Pkg_W Cor_W GFX_W
|
||||
0.06 0.80 2.29 0.11 0.00 0.00 99.83 47 40 0.26 0.01 0.44 98.78 3.49 0.12 0.14
|
||||
0 0 0.07 0.80 2.29 0.07 0.00 0.00 99.86 40 40 0.26 0.01 0.44 98.78 3.49 0.12 0.14
|
||||
0 4 0.03 0.80 2.29 0.12
|
||||
1 1 0.04 0.80 2.29 0.25 0.01 0.00 99.71 40
|
||||
1 5 0.16 0.80 2.29 0.13
|
||||
2 2 0.05 0.80 2.29 0.06 0.01 0.00 99.88 40
|
||||
2 6 0.03 0.80 2.29 0.08
|
||||
3 3 0.05 0.80 2.29 0.08 0.00 0.00 99.87 47
|
||||
3 7 0.04 0.84 2.29 0.09
|
||||
.fi
|
||||
.SH SUMMARY EXAMPLE
|
||||
The "-s" option prints the column headers just once,
|
||||
and then the one line system summary for each sample interval.
|
||||
|
||||
.nf
|
||||
[root@wsm]# turbostat -S
|
||||
%c0 GHz TSC %c1 %c3 %c6 CTMP %pc3 %pc6
|
||||
1.40 2.81 3.38 10.78 43.47 44.35 42 13.67 2.09
|
||||
1.34 2.90 3.38 11.48 58.96 28.23 41 19.89 0.15
|
||||
1.55 2.72 3.38 26.73 37.66 34.07 42 2.53 2.80
|
||||
1.37 2.83 3.38 16.95 60.05 21.63 42 5.76 0.20
|
||||
[root@ivy]# ./turbostat
|
||||
Core CPU Avg_MHz %Busy Bzy_MHz TSC_MHz SMI CPU%c1 CPU%c3 CPU%c6 CPU%c7 CoreTmp PkgTmp Pkg%pc2 Pkg%pc3 Pkg%pc6 Pkg%pc7 PkgWatt CorWatt GFXWatt
|
||||
- - 6 0.36 1596 3492 0 0.59 0.01 99.04 0.00 23 24 23.82 0.01 72.47 0.00 6.40 1.01 0.00
|
||||
0 0 9 0.58 1596 3492 0 0.28 0.01 99.13 0.00 23 24 23.82 0.01 72.47 0.00 6.40 1.01 0.00
|
||||
0 4 1 0.07 1596 3492 0 0.79
|
||||
1 1 10 0.65 1596 3492 0 0.59 0.00 98.76 0.00 23
|
||||
1 5 5 0.28 1596 3492 0 0.95
|
||||
2 2 10 0.66 1596 3492 0 0.41 0.01 98.92 0.00 23
|
||||
2 6 2 0.10 1597 3492 0 0.97
|
||||
3 3 3 0.20 1596 3492 0 0.44 0.00 99.37 0.00 23
|
||||
3 7 5 0.31 1596 3492 0 0.33
|
||||
.fi
|
||||
.SH VERBOSE EXAMPLE
|
||||
The "-v" option adds verbosity to the output:
|
||||
|
@ -154,55 +143,35 @@ eg. Here a cycle soaker is run on 1 CPU (see %c0) for a few seconds
|
|||
until ^C while the other CPUs are mostly idle:
|
||||
|
||||
.nf
|
||||
[root@x980 lenb]# ./turbostat cat /dev/zero > /dev/null
|
||||
root@ivy: turbostat cat /dev/zero > /dev/null
|
||||
^C
|
||||
cor CPU %c0 GHz TSC %c1 %c3 %c6 %pc3 %pc6
|
||||
8.86 3.61 3.38 15.06 31.19 44.89 0.00 0.00
|
||||
0 0 1.46 3.22 3.38 16.84 29.48 52.22 0.00 0.00
|
||||
0 6 0.21 3.06 3.38 18.09
|
||||
1 2 0.53 3.33 3.38 2.80 46.40 50.27
|
||||
1 8 0.89 3.47 3.38 2.44
|
||||
2 4 1.36 3.43 3.38 9.04 23.71 65.89
|
||||
2 10 0.18 2.86 3.38 10.22
|
||||
8 1 0.04 2.87 3.38 99.96 0.01 0.00
|
||||
8 7 99.72 3.63 3.38 0.27
|
||||
9 3 0.31 3.21 3.38 7.64 56.55 35.50
|
||||
9 9 0.08 2.95 3.38 7.88
|
||||
10 5 1.42 3.43 3.38 2.14 30.99 65.44
|
||||
10 11 0.16 2.88 3.38 3.40
|
||||
Core CPU Avg_MHz %Busy Bzy_MHz TSC_MHz SMI CPU%c1 CPU%c3 CPU%c6 CPU%c7 CoreTmp PkgTmp Pkg%pc2 Pkg%pc3 Pkg%pc6 Pkg%pc7 PkgWatt CorWatt GFXWatt
|
||||
- - 496 12.75 3886 3492 0 13.16 0.04 74.04 0.00 36 36 0.00 0.00 0.00 0.00 23.15 17.65 0.00
|
||||
0 0 22 0.57 3830 3492 0 0.83 0.02 98.59 0.00 27 36 0.00 0.00 0.00 0.00 23.15 17.65 0.00
|
||||
0 4 9 0.24 3829 3492 0 1.15
|
||||
1 1 4 0.09 3783 3492 0 99.91 0.00 0.00 0.00 36
|
||||
1 5 3880 99.82 3888 3492 0 0.18
|
||||
2 2 17 0.44 3813 3492 0 0.77 0.04 98.75 0.00 28
|
||||
2 6 12 0.32 3823 3492 0 0.89
|
||||
3 3 16 0.43 3844 3492 0 0.63 0.11 98.84 0.00 30
|
||||
3 7 4 0.11 3827 3492 0 0.94
|
||||
30.372243 sec
|
||||
|
||||
.fi
|
||||
Above the cycle soaker drives cpu7 up its 3.6 GHz turbo limit
|
||||
Above the cycle soaker drives cpu5 up its 3.8 GHz turbo limit
|
||||
while the other processors are generally in various states of idle.
|
||||
|
||||
Note that cpu1 and cpu7 are HT siblings within core8.
|
||||
As cpu7 is very busy, it prevents its sibling, cpu1,
|
||||
Note that cpu1 and cpu5 are HT siblings within core1.
|
||||
As cpu5 is very busy, it prevents its sibling, cpu1,
|
||||
from entering a c-state deeper than c1.
|
||||
|
||||
Note that turbostat reports average GHz of 3.63, while
|
||||
the arithmetic average of the GHz column above is lower.
|
||||
This is a weighted average, where the weight is %c0. ie. it is the total number of
|
||||
un-halted cycles elapsed per time divided by the number of CPUs.
|
||||
.SH SMI COUNTING EXAMPLE
|
||||
On Intel Nehalem and newer processors, MSR 0x34 is a System Management Mode Interrupt (SMI) counter.
|
||||
This counter is shown by default under the "SMI" column.
|
||||
.nf
|
||||
[root@x980 ~]# turbostat
|
||||
cor CPU %c0 GHz TSC SMI %c1 %c3 %c6 CTMP %pc3 %pc6
|
||||
0.11 1.91 3.38 0 1.84 0.26 97.79 29 0.82 83.87
|
||||
0 0 0.40 1.63 3.38 0 10.27 0.12 89.20 20 0.82 83.88
|
||||
0 6 0.06 1.63 3.38 0 10.61
|
||||
1 2 0.37 2.63 3.38 0 0.02 0.10 99.51 22
|
||||
1 8 0.01 1.62 3.38 0 0.39
|
||||
2 4 0.07 1.62 3.38 0 0.04 0.07 99.82 23
|
||||
2 10 0.02 1.62 3.38 0 0.09
|
||||
8 1 0.23 1.64 3.38 0 0.10 1.07 98.60 24
|
||||
8 7 0.02 1.64 3.38 0 0.31
|
||||
9 3 0.03 1.62 3.38 0 0.03 0.05 99.89 29
|
||||
9 9 0.02 1.62 3.38 0 0.05
|
||||
10 5 0.07 1.62 3.38 0 0.08 0.12 99.73 27
|
||||
10 11 0.03 1.62 3.38 0 0.13
|
||||
^C
|
||||
.fi
|
||||
Note that the Avg_MHz column reflects the total number of cycles executed
|
||||
divided by the measurement interval. If the %Busy column is 100%,
|
||||
then the processor was running at that speed the entire interval.
|
||||
The Avg_MHz multiplied by the %Busy results in the Bzy_MHz --
|
||||
which is the average frequency while the processor was executing --
|
||||
not including any non-busy idle time.
|
||||
|
||||
.SH NOTES
|
||||
|
||||
.B "turbostat "
|
||||
|
|
|
@ -56,7 +56,7 @@ unsigned int do_slm_cstates;
|
|||
unsigned int use_c1_residency_msr;
|
||||
unsigned int has_aperf;
|
||||
unsigned int has_epb;
|
||||
unsigned int units = 1000000000; /* Ghz etc */
|
||||
unsigned int units = 1000000; /* MHz etc */
|
||||
unsigned int genuine_intel;
|
||||
unsigned int has_invariant_tsc;
|
||||
unsigned int do_nehalem_platform_info;
|
||||
|
@ -264,88 +264,93 @@ int get_msr(int cpu, off_t offset, unsigned long long *msr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Example Format w/ field column widths:
|
||||
*
|
||||
* Package Core CPU Avg_MHz Bzy_MHz TSC_MHz SMI %Busy CPU_%c1 CPU_%c3 CPU_%c6 CPU_%c7 CoreTmp PkgTmp Pkg%pc2 Pkg%pc3 Pkg%pc6 Pkg%pc7 PkgWatt CorWatt GFXWatt
|
||||
* 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567
|
||||
*/
|
||||
|
||||
void print_header(void)
|
||||
{
|
||||
if (show_pkg)
|
||||
outp += sprintf(outp, "pk");
|
||||
if (show_pkg)
|
||||
outp += sprintf(outp, " ");
|
||||
outp += sprintf(outp, "Package ");
|
||||
if (show_core)
|
||||
outp += sprintf(outp, "cor");
|
||||
outp += sprintf(outp, " Core ");
|
||||
if (show_cpu)
|
||||
outp += sprintf(outp, " CPU");
|
||||
if (show_pkg || show_core || show_cpu)
|
||||
outp += sprintf(outp, " ");
|
||||
if (do_nhm_cstates)
|
||||
outp += sprintf(outp, " %%c0");
|
||||
outp += sprintf(outp, " CPU ");
|
||||
if (has_aperf)
|
||||
outp += sprintf(outp, " GHz");
|
||||
outp += sprintf(outp, " TSC");
|
||||
outp += sprintf(outp, "Avg_MHz ");
|
||||
if (do_nhm_cstates)
|
||||
outp += sprintf(outp, " %%Busy ");
|
||||
if (has_aperf)
|
||||
outp += sprintf(outp, "Bzy_MHz ");
|
||||
outp += sprintf(outp, "TSC_MHz ");
|
||||
if (do_smi)
|
||||
outp += sprintf(outp, " SMI");
|
||||
outp += sprintf(outp, " SMI ");
|
||||
if (extra_delta_offset32)
|
||||
outp += sprintf(outp, " count 0x%03X", extra_delta_offset32);
|
||||
outp += sprintf(outp, " count 0x%03X ", extra_delta_offset32);
|
||||
if (extra_delta_offset64)
|
||||
outp += sprintf(outp, " COUNT 0x%03X", extra_delta_offset64);
|
||||
outp += sprintf(outp, " COUNT 0x%03X ", extra_delta_offset64);
|
||||
if (extra_msr_offset32)
|
||||
outp += sprintf(outp, " MSR 0x%03X", extra_msr_offset32);
|
||||
outp += sprintf(outp, " MSR 0x%03X ", extra_msr_offset32);
|
||||
if (extra_msr_offset64)
|
||||
outp += sprintf(outp, " MSR 0x%03X", extra_msr_offset64);
|
||||
outp += sprintf(outp, " MSR 0x%03X ", extra_msr_offset64);
|
||||
if (do_nhm_cstates)
|
||||
outp += sprintf(outp, " %%c1");
|
||||
outp += sprintf(outp, " CPU%%c1 ");
|
||||
if (do_nhm_cstates && !do_slm_cstates)
|
||||
outp += sprintf(outp, " %%c3");
|
||||
outp += sprintf(outp, " CPU%%c3 ");
|
||||
if (do_nhm_cstates)
|
||||
outp += sprintf(outp, " %%c6");
|
||||
outp += sprintf(outp, " CPU%%c6 ");
|
||||
if (do_snb_cstates)
|
||||
outp += sprintf(outp, " %%c7");
|
||||
outp += sprintf(outp, " CPU%%c7 ");
|
||||
|
||||
if (do_dts)
|
||||
outp += sprintf(outp, " CTMP");
|
||||
outp += sprintf(outp, "CoreTmp ");
|
||||
if (do_ptm)
|
||||
outp += sprintf(outp, " PTMP");
|
||||
outp += sprintf(outp, " PkgTmp ");
|
||||
|
||||
if (do_snb_cstates)
|
||||
outp += sprintf(outp, " %%pc2");
|
||||
outp += sprintf(outp, "Pkg%%pc2 ");
|
||||
if (do_nhm_cstates && !do_slm_cstates)
|
||||
outp += sprintf(outp, " %%pc3");
|
||||
outp += sprintf(outp, "Pkg%%pc3 ");
|
||||
if (do_nhm_cstates && !do_slm_cstates)
|
||||
outp += sprintf(outp, " %%pc6");
|
||||
outp += sprintf(outp, "Pkg%%pc6 ");
|
||||
if (do_snb_cstates)
|
||||
outp += sprintf(outp, " %%pc7");
|
||||
outp += sprintf(outp, "Pkg%%pc7 ");
|
||||
if (do_c8_c9_c10) {
|
||||
outp += sprintf(outp, " %%pc8");
|
||||
outp += sprintf(outp, " %%pc9");
|
||||
outp += sprintf(outp, " %%pc10");
|
||||
outp += sprintf(outp, "Pkg%%pc8 ");
|
||||
outp += sprintf(outp, "Pkg%%pc9 ");
|
||||
outp += sprintf(outp, "Pk%%pc10 ");
|
||||
}
|
||||
|
||||
if (do_rapl && !rapl_joules) {
|
||||
if (do_rapl & RAPL_PKG)
|
||||
outp += sprintf(outp, " Pkg_W");
|
||||
outp += sprintf(outp, "PkgWatt ");
|
||||
if (do_rapl & RAPL_CORES)
|
||||
outp += sprintf(outp, " Cor_W");
|
||||
outp += sprintf(outp, "CorWatt ");
|
||||
if (do_rapl & RAPL_GFX)
|
||||
outp += sprintf(outp, " GFX_W");
|
||||
outp += sprintf(outp, "GFXWatt ");
|
||||
if (do_rapl & RAPL_DRAM)
|
||||
outp += sprintf(outp, " RAM_W");
|
||||
outp += sprintf(outp, "RAMWatt ");
|
||||
if (do_rapl & RAPL_PKG_PERF_STATUS)
|
||||
outp += sprintf(outp, " PKG_%%");
|
||||
outp += sprintf(outp, " PKG_%% ");
|
||||
if (do_rapl & RAPL_DRAM_PERF_STATUS)
|
||||
outp += sprintf(outp, " RAM_%%");
|
||||
outp += sprintf(outp, " RAM_%% ");
|
||||
} else {
|
||||
if (do_rapl & RAPL_PKG)
|
||||
outp += sprintf(outp, " Pkg_J");
|
||||
outp += sprintf(outp, " Pkg_J ");
|
||||
if (do_rapl & RAPL_CORES)
|
||||
outp += sprintf(outp, " Cor_J");
|
||||
outp += sprintf(outp, " Cor_J ");
|
||||
if (do_rapl & RAPL_GFX)
|
||||
outp += sprintf(outp, " GFX_J");
|
||||
outp += sprintf(outp, " GFX_J ");
|
||||
if (do_rapl & RAPL_DRAM)
|
||||
outp += sprintf(outp, " RAM_W");
|
||||
outp += sprintf(outp, " RAM_W ");
|
||||
if (do_rapl & RAPL_PKG_PERF_STATUS)
|
||||
outp += sprintf(outp, " PKG_%%");
|
||||
outp += sprintf(outp, " PKG_%% ");
|
||||
if (do_rapl & RAPL_DRAM_PERF_STATUS)
|
||||
outp += sprintf(outp, " RAM_%%");
|
||||
outp += sprintf(outp, " time");
|
||||
outp += sprintf(outp, " RAM_%% ");
|
||||
outp += sprintf(outp, " time ");
|
||||
|
||||
}
|
||||
outp += sprintf(outp, "\n");
|
||||
|
@ -410,25 +415,12 @@ int dump_counters(struct thread_data *t, struct core_data *c,
|
|||
|
||||
/*
|
||||
* column formatting convention & formats
|
||||
* package: "pk" 2 columns %2d
|
||||
* core: "cor" 3 columns %3d
|
||||
* CPU: "CPU" 3 columns %3d
|
||||
* Pkg_W: %6.2
|
||||
* Cor_W: %6.2
|
||||
* GFX_W: %5.2
|
||||
* RAM_W: %5.2
|
||||
* GHz: "GHz" 3 columns %3.2
|
||||
* TSC: "TSC" 3 columns %3.2
|
||||
* SMI: "SMI" 4 columns %4d
|
||||
* percentage " %pc3" %6.2
|
||||
* Perf Status percentage: %5.2
|
||||
* "CTMP" 4 columns %4d
|
||||
*/
|
||||
int format_counters(struct thread_data *t, struct core_data *c,
|
||||
struct pkg_data *p)
|
||||
{
|
||||
double interval_float;
|
||||
char *fmt5, *fmt6;
|
||||
char *fmt8;
|
||||
|
||||
/* if showing only 1st thread in core and this isn't one, bail out */
|
||||
if (show_core_only && !(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
|
||||
|
@ -443,65 +435,52 @@ int format_counters(struct thread_data *t, struct core_data *c,
|
|||
/* topo columns, print blanks on 1st (average) line */
|
||||
if (t == &average.threads) {
|
||||
if (show_pkg)
|
||||
outp += sprintf(outp, " ");
|
||||
if (show_pkg && show_core)
|
||||
outp += sprintf(outp, " ");
|
||||
outp += sprintf(outp, " -");
|
||||
if (show_core)
|
||||
outp += sprintf(outp, " ");
|
||||
outp += sprintf(outp, " -");
|
||||
if (show_cpu)
|
||||
outp += sprintf(outp, " " " ");
|
||||
outp += sprintf(outp, " -");
|
||||
} else {
|
||||
if (show_pkg) {
|
||||
if (p)
|
||||
outp += sprintf(outp, "%2d", p->package_id);
|
||||
outp += sprintf(outp, "%8d", p->package_id);
|
||||
else
|
||||
outp += sprintf(outp, " ");
|
||||
outp += sprintf(outp, " -");
|
||||
}
|
||||
if (show_pkg && show_core)
|
||||
outp += sprintf(outp, " ");
|
||||
if (show_core) {
|
||||
if (c)
|
||||
outp += sprintf(outp, "%3d", c->core_id);
|
||||
outp += sprintf(outp, "%8d", c->core_id);
|
||||
else
|
||||
outp += sprintf(outp, " ");
|
||||
outp += sprintf(outp, " -");
|
||||
}
|
||||
if (show_cpu)
|
||||
outp += sprintf(outp, " %3d", t->cpu_id);
|
||||
outp += sprintf(outp, "%8d", t->cpu_id);
|
||||
}
|
||||
|
||||
/* AvgMHz */
|
||||
if (has_aperf)
|
||||
outp += sprintf(outp, "%8.0f",
|
||||
1.0 / units * t->aperf / interval_float);
|
||||
|
||||
/* %c0 */
|
||||
if (do_nhm_cstates) {
|
||||
if (show_pkg || show_core || show_cpu)
|
||||
outp += sprintf(outp, " ");
|
||||
if (!skip_c0)
|
||||
outp += sprintf(outp, "%6.2f", 100.0 * t->mperf/t->tsc);
|
||||
outp += sprintf(outp, "%8.2f", 100.0 * t->mperf/t->tsc);
|
||||
else
|
||||
outp += sprintf(outp, " ****");
|
||||
outp += sprintf(outp, "********");
|
||||
}
|
||||
|
||||
/* GHz */
|
||||
if (has_aperf) {
|
||||
if (!aperf_mperf_unstable) {
|
||||
outp += sprintf(outp, " %3.2f",
|
||||
1.0 * t->tsc / units * t->aperf /
|
||||
t->mperf / interval_float);
|
||||
} else {
|
||||
if (t->aperf > t->tsc || t->mperf > t->tsc) {
|
||||
outp += sprintf(outp, " ***");
|
||||
} else {
|
||||
outp += sprintf(outp, "%3.1f*",
|
||||
1.0 * t->tsc /
|
||||
units * t->aperf /
|
||||
t->mperf / interval_float);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* BzyMHz */
|
||||
if (has_aperf)
|
||||
outp += sprintf(outp, "%8.0f",
|
||||
1.0 * t->tsc / units * t->aperf / t->mperf / interval_float);
|
||||
|
||||
/* TSC */
|
||||
outp += sprintf(outp, "%5.2f", 1.0 * t->tsc/units/interval_float);
|
||||
outp += sprintf(outp, "%8.0f", 1.0 * t->tsc/units/interval_float);
|
||||
|
||||
/* SMI */
|
||||
if (do_smi)
|
||||
outp += sprintf(outp, "%4d", t->smi_count);
|
||||
outp += sprintf(outp, "%8d", t->smi_count);
|
||||
|
||||
/* delta */
|
||||
if (extra_delta_offset32)
|
||||
|
@ -520,9 +499,9 @@ int format_counters(struct thread_data *t, struct core_data *c,
|
|||
|
||||
if (do_nhm_cstates) {
|
||||
if (!skip_c1)
|
||||
outp += sprintf(outp, " %6.2f", 100.0 * t->c1/t->tsc);
|
||||
outp += sprintf(outp, "%8.2f", 100.0 * t->c1/t->tsc);
|
||||
else
|
||||
outp += sprintf(outp, " ****");
|
||||
outp += sprintf(outp, "********");
|
||||
}
|
||||
|
||||
/* print per-core data only for 1st thread in core */
|
||||
|
@ -530,79 +509,76 @@ int format_counters(struct thread_data *t, struct core_data *c,
|
|||
goto done;
|
||||
|
||||
if (do_nhm_cstates && !do_slm_cstates)
|
||||
outp += sprintf(outp, " %6.2f", 100.0 * c->c3/t->tsc);
|
||||
outp += sprintf(outp, "%8.2f", 100.0 * c->c3/t->tsc);
|
||||
if (do_nhm_cstates)
|
||||
outp += sprintf(outp, " %6.2f", 100.0 * c->c6/t->tsc);
|
||||
outp += sprintf(outp, "%8.2f", 100.0 * c->c6/t->tsc);
|
||||
if (do_snb_cstates)
|
||||
outp += sprintf(outp, " %6.2f", 100.0 * c->c7/t->tsc);
|
||||
outp += sprintf(outp, "%8.2f", 100.0 * c->c7/t->tsc);
|
||||
|
||||
if (do_dts)
|
||||
outp += sprintf(outp, " %4d", c->core_temp_c);
|
||||
outp += sprintf(outp, "%8d", c->core_temp_c);
|
||||
|
||||
/* print per-package data only for 1st core in package */
|
||||
if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
|
||||
goto done;
|
||||
|
||||
if (do_ptm)
|
||||
outp += sprintf(outp, " %4d", p->pkg_temp_c);
|
||||
outp += sprintf(outp, "%8d", p->pkg_temp_c);
|
||||
|
||||
if (do_snb_cstates)
|
||||
outp += sprintf(outp, " %6.2f", 100.0 * p->pc2/t->tsc);
|
||||
outp += sprintf(outp, "%8.2f", 100.0 * p->pc2/t->tsc);
|
||||
if (do_nhm_cstates && !do_slm_cstates)
|
||||
outp += sprintf(outp, " %6.2f", 100.0 * p->pc3/t->tsc);
|
||||
outp += sprintf(outp, "%8.2f", 100.0 * p->pc3/t->tsc);
|
||||
if (do_nhm_cstates && !do_slm_cstates)
|
||||
outp += sprintf(outp, " %6.2f", 100.0 * p->pc6/t->tsc);
|
||||
outp += sprintf(outp, "%8.2f", 100.0 * p->pc6/t->tsc);
|
||||
if (do_snb_cstates)
|
||||
outp += sprintf(outp, " %6.2f", 100.0 * p->pc7/t->tsc);
|
||||
outp += sprintf(outp, "%8.2f", 100.0 * p->pc7/t->tsc);
|
||||
if (do_c8_c9_c10) {
|
||||
outp += sprintf(outp, " %6.2f", 100.0 * p->pc8/t->tsc);
|
||||
outp += sprintf(outp, " %6.2f", 100.0 * p->pc9/t->tsc);
|
||||
outp += sprintf(outp, " %6.2f", 100.0 * p->pc10/t->tsc);
|
||||
outp += sprintf(outp, "%8.2f", 100.0 * p->pc8/t->tsc);
|
||||
outp += sprintf(outp, "%8.2f", 100.0 * p->pc9/t->tsc);
|
||||
outp += sprintf(outp, "%8.2f", 100.0 * p->pc10/t->tsc);
|
||||
}
|
||||
|
||||
/*
|
||||
* If measurement interval exceeds minimum RAPL Joule Counter range,
|
||||
* indicate that results are suspect by printing "**" in fraction place.
|
||||
*/
|
||||
if (interval_float < rapl_joule_counter_range) {
|
||||
fmt5 = " %5.2f";
|
||||
fmt6 = " %6.2f";
|
||||
} else {
|
||||
fmt5 = " %3.0f**";
|
||||
fmt6 = " %4.0f**";
|
||||
}
|
||||
if (interval_float < rapl_joule_counter_range)
|
||||
fmt8 = "%8.2f";
|
||||
else
|
||||
fmt8 = " %6.0f**";
|
||||
|
||||
if (do_rapl && !rapl_joules) {
|
||||
if (do_rapl & RAPL_PKG)
|
||||
outp += sprintf(outp, fmt6, p->energy_pkg * rapl_energy_units / interval_float);
|
||||
outp += sprintf(outp, fmt8, p->energy_pkg * rapl_energy_units / interval_float);
|
||||
if (do_rapl & RAPL_CORES)
|
||||
outp += sprintf(outp, fmt6, p->energy_cores * rapl_energy_units / interval_float);
|
||||
outp += sprintf(outp, fmt8, p->energy_cores * rapl_energy_units / interval_float);
|
||||
if (do_rapl & RAPL_GFX)
|
||||
outp += sprintf(outp, fmt5, p->energy_gfx * rapl_energy_units / interval_float);
|
||||
outp += sprintf(outp, fmt8, p->energy_gfx * rapl_energy_units / interval_float);
|
||||
if (do_rapl & RAPL_DRAM)
|
||||
outp += sprintf(outp, fmt5, p->energy_dram * rapl_energy_units / interval_float);
|
||||
outp += sprintf(outp, fmt8, p->energy_dram * rapl_energy_units / interval_float);
|
||||
if (do_rapl & RAPL_PKG_PERF_STATUS)
|
||||
outp += sprintf(outp, fmt5, 100.0 * p->rapl_pkg_perf_status * rapl_time_units / interval_float);
|
||||
outp += sprintf(outp, fmt8, 100.0 * p->rapl_pkg_perf_status * rapl_time_units / interval_float);
|
||||
if (do_rapl & RAPL_DRAM_PERF_STATUS)
|
||||
outp += sprintf(outp, fmt5, 100.0 * p->rapl_dram_perf_status * rapl_time_units / interval_float);
|
||||
outp += sprintf(outp, fmt8, 100.0 * p->rapl_dram_perf_status * rapl_time_units / interval_float);
|
||||
} else {
|
||||
if (do_rapl & RAPL_PKG)
|
||||
outp += sprintf(outp, fmt6,
|
||||
outp += sprintf(outp, fmt8,
|
||||
p->energy_pkg * rapl_energy_units);
|
||||
if (do_rapl & RAPL_CORES)
|
||||
outp += sprintf(outp, fmt6,
|
||||
outp += sprintf(outp, fmt8,
|
||||
p->energy_cores * rapl_energy_units);
|
||||
if (do_rapl & RAPL_GFX)
|
||||
outp += sprintf(outp, fmt5,
|
||||
outp += sprintf(outp, fmt8,
|
||||
p->energy_gfx * rapl_energy_units);
|
||||
if (do_rapl & RAPL_DRAM)
|
||||
outp += sprintf(outp, fmt5,
|
||||
outp += sprintf(outp, fmt8,
|
||||
p->energy_dram * rapl_energy_units);
|
||||
if (do_rapl & RAPL_PKG_PERF_STATUS)
|
||||
outp += sprintf(outp, fmt5, 100.0 * p->rapl_pkg_perf_status * rapl_time_units / interval_float);
|
||||
outp += sprintf(outp, fmt8, 100.0 * p->rapl_pkg_perf_status * rapl_time_units / interval_float);
|
||||
if (do_rapl & RAPL_DRAM_PERF_STATUS)
|
||||
outp += sprintf(outp, fmt5, 100.0 * p->rapl_dram_perf_status * rapl_time_units / interval_float);
|
||||
outp += sprintf(outp, fmt5, interval_float);
|
||||
outp += sprintf(outp, fmt8, 100.0 * p->rapl_dram_perf_status * rapl_time_units / interval_float);
|
||||
outp += sprintf(outp, fmt8, interval_float);
|
||||
|
||||
}
|
||||
done:
|
||||
|
@ -1516,6 +1492,9 @@ int has_nehalem_turbo_ratio_limit(unsigned int family, unsigned int model)
|
|||
case 0x46: /* HSW */
|
||||
case 0x37: /* BYT */
|
||||
case 0x4D: /* AVN */
|
||||
case 0x3D: /* BDW */
|
||||
case 0x4F: /* BDX */
|
||||
case 0x56: /* BDX-DE */
|
||||
return 1;
|
||||
case 0x2E: /* Nehalem-EX Xeon - Beckton */
|
||||
case 0x2F: /* Westmere-EX Xeon - Eagleton */
|
||||
|
@ -1629,9 +1608,12 @@ void rapl_probe(unsigned int family, unsigned int model)
|
|||
case 0x3C: /* HSW */
|
||||
case 0x45: /* HSW */
|
||||
case 0x46: /* HSW */
|
||||
case 0x3D: /* BDW */
|
||||
do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_GFX | RAPL_PKG_POWER_INFO;
|
||||
break;
|
||||
case 0x3F: /* HSX */
|
||||
case 0x4F: /* BDX */
|
||||
case 0x56: /* BDX-DE */
|
||||
do_rapl = RAPL_PKG | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO;
|
||||
break;
|
||||
case 0x2D:
|
||||
|
@ -1875,6 +1857,9 @@ int is_snb(unsigned int family, unsigned int model)
|
|||
case 0x3F: /* HSW */
|
||||
case 0x45: /* HSW */
|
||||
case 0x46: /* HSW */
|
||||
case 0x3D: /* BDW */
|
||||
case 0x4F: /* BDX */
|
||||
case 0x56: /* BDX-DE */
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -1886,7 +1871,8 @@ int has_c8_c9_c10(unsigned int family, unsigned int model)
|
|||
return 0;
|
||||
|
||||
switch (model) {
|
||||
case 0x45:
|
||||
case 0x45: /* HSW */
|
||||
case 0x3D: /* BDW */
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -2455,7 +2441,7 @@ int main(int argc, char **argv)
|
|||
cmdline(argc, argv);
|
||||
|
||||
if (verbose)
|
||||
fprintf(stderr, "turbostat v3.6 Dec 2, 2013"
|
||||
fprintf(stderr, "turbostat v3.7 Feb 6, 2014"
|
||||
" - Len Brown <lenb@kernel.org>\n");
|
||||
|
||||
turbostat_init();
|
||||
|
|
|
@ -277,7 +277,7 @@ int kvm_timer_hyp_init(void)
|
|||
|
||||
host_vtimer_irq = ppi;
|
||||
|
||||
err = register_cpu_notifier(&kvm_timer_cpu_nb);
|
||||
err = __register_cpu_notifier(&kvm_timer_cpu_nb);
|
||||
if (err) {
|
||||
kvm_err("Cannot register timer CPU notifier\n");
|
||||
goto out_free;
|
||||
|
|
|
@ -1496,7 +1496,7 @@ int kvm_vgic_hyp_init(void)
|
|||
goto out;
|
||||
}
|
||||
|
||||
ret = register_cpu_notifier(&vgic_cpu_nb);
|
||||
ret = __register_cpu_notifier(&vgic_cpu_nb);
|
||||
if (ret) {
|
||||
kvm_err("Cannot register vgic CPU notifier\n");
|
||||
goto out_free_irq;
|
||||
|
|
Loading…
Reference in New Issue