From 02c4fae9ea68fc41ebe871c635408daa2ba37d2e Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Fri, 17 Jun 2016 01:28:33 -0400 Subject: drivers/idle: make intel_idle.c driver more explicitly non-modular The Kconfig for this driver is currently declared with: config INTEL_IDLE bool "Cpuidle Driver for Intel Processors" ...meaning that it currently is not being built as a module by anyone. This was done in commit 6ce9cd8669fa1195fdc21643370e34523c7ac988 ("intel_idle: disable module support") since "...the module capability is cauing more trouble than it is worth." This was done over 5y ago, and Daniel adds that: ...the modular support has been removed from almost all the cpuidle drivers and the cpuidle framework is no longer assuming driver could be unloaded. Removing the modular dead code in the driver makes sense as this what have been done in the others drivers. So lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. Since module_init translates to device_initcall in the non-modular case, the init ordering remains unchanged with this commit. At a later date we might want to consider whether subsys_init or another init category seems more appropriate than device_init. We replace module.h with moduleparam.h since the file does declare some module parameters, and leaving them as such is currently the easiest way to remain compatible with existing boot arg use cases. Note that MODULE_DEVICE_TABLE is a no-op for non-modular code. Also note that we can't remove intel_idle_cpuidle_devices_uninit() as that is still used for unwind purposes if the init fails. We also delete the MODULE_LICENSE tag etc. since all that information is already contained at the top of the file in the comments. Signed-off-by: Paul Gortmaker Signed-off-by: Len Brown Signed-off-by: Rafael J. Wysocki diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index b5dd41d..4c8b23d 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -46,8 +46,6 @@ * to avoid complications with the lapic timer workaround. * Have not seen issues with suspend, but may need same workaround here. * - * There is currently no kernel-based automatic probing/loading mechanism - * if the driver is built as a module. */ /* un-comment DEBUG to enable pr_debug() statements */ @@ -60,7 +58,7 @@ #include #include #include -#include +#include #include #include #include @@ -1055,7 +1053,6 @@ static const struct x86_cpu_id intel_idle_ids[] __initconst = { ICPU(INTEL_FAM6_ATOM_GOLDMONT, idle_cpu_bxt), {} }; -MODULE_DEVICE_TABLE(x86cpu, intel_idle_ids); /* * intel_idle_probe() @@ -1416,34 +1413,12 @@ static int __init intel_idle_init(void) return 0; } +device_initcall(intel_idle_init); -static void __exit intel_idle_exit(void) -{ - struct cpuidle_device *dev; - int i; - - cpu_notifier_register_begin(); - - if (lapic_timer_reliable_states != LAPIC_TIMER_ALWAYS_RELIABLE) - on_each_cpu(__setup_broadcast_timer, (void *)false, 1); - __unregister_cpu_notifier(&cpu_hotplug_notifier); - - for_each_possible_cpu(i) { - dev = per_cpu_ptr(intel_idle_cpuidle_devices, i); - cpuidle_unregister_device(dev); - } - - cpu_notifier_register_done(); - - cpuidle_unregister_driver(&intel_idle_driver); - free_percpu(intel_idle_cpuidle_devices); -} - -module_init(intel_idle_init); -module_exit(intel_idle_exit); - +/* + * We are not really modular, but we used to support that. Meaning we also + * support "intel_idle.max_cstate=..." at boot and also a read-only export of + * it at /sys/module/intel_idle/parameters/max_cstate -- so using module_param + * is the easiest way (currently) to continue doing that. + */ module_param(max_cstate, int, 0444); - -MODULE_AUTHOR("Len Brown "); -MODULE_DESCRIPTION("Cpuidle driver for Intel Hardware v" INTEL_IDLE_VERSION); -MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 0080d65b7719fc58e60b5595fc61acded330004f Mon Sep 17 00:00:00 2001 From: Jacob Pan Date: Fri, 17 Jun 2016 01:28:34 -0400 Subject: idle_intel: Add Denverton Denverton is an Intel Atom based micro server which shares the same Goldmont architecture as Broxton. The available C-states on Denverton is a subset of Broxton with only C1, C1e, and C6. Signed-off-by: Jacob Pan Signed-off-by: Len Brown Signed-off-by: Rafael J. Wysocki diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 4c8b23d..170ab8e 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -826,6 +826,35 @@ static struct cpuidle_state bxt_cstates[] = { .enter = NULL } }; +static struct cpuidle_state dnv_cstates[] = { + { + .name = "C1-DNV", + .desc = "MWAIT 0x00", + .flags = MWAIT2flg(0x00), + .exit_latency = 2, + .target_residency = 2, + .enter = &intel_idle, + .enter_freeze = intel_idle_freeze, }, + { + .name = "C1E-DNV", + .desc = "MWAIT 0x01", + .flags = MWAIT2flg(0x01), + .exit_latency = 10, + .target_residency = 20, + .enter = &intel_idle, + .enter_freeze = intel_idle_freeze, }, + { + .name = "C6-DNV", + .desc = "MWAIT 0x20", + .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, + .exit_latency = 50, + .target_residency = 500, + .enter = &intel_idle, + .enter_freeze = intel_idle_freeze, }, + { + .enter = NULL } +}; + /** * intel_idle * @dev: cpuidle_device @@ -1015,6 +1044,11 @@ static const struct idle_cpu idle_cpu_bxt = { .disable_promotion_to_c1e = true, }; +static const struct idle_cpu idle_cpu_dnv = { + .state_table = dnv_cstates, + .disable_promotion_to_c1e = true, +}; + #define ICPU(model, cpu) \ { X86_VENDOR_INTEL, 6, model, X86_FEATURE_MWAIT, (unsigned long)&cpu } @@ -1051,6 +1085,7 @@ static const struct x86_cpu_id intel_idle_ids[] __initconst = { ICPU(INTEL_FAM6_SKYLAKE_X, idle_cpu_skx), ICPU(INTEL_FAM6_XEON_PHI_KNL, idle_cpu_knl), ICPU(INTEL_FAM6_ATOM_GOLDMONT, idle_cpu_bxt), + ICPU(INTEL_FAM6_ATOM_DENVERTON, idle_cpu_dnv), {} }; -- cgit v0.10.2 From 3451ab3ebf92b12801878d8b5c94845afd4219f0 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Mon, 27 Jun 2016 00:35:12 -0600 Subject: intel_idle: re-work bxt_idle_state_table_update() and its helper Since irtl_ns_units[] has itself zero entries, make sure the caller recognized those cases along with the MSR read returning zero, as zero is not a valid value for exit_latency and target_residency. Signed-off-by: Jan Beulich Signed-off-by: Rafael J. Wysocki diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 170ab8e..5300f25 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -1187,6 +1187,9 @@ static unsigned long long irtl_2_usec(unsigned long long irtl) { unsigned long long ns; + if (!irtl) + return 0; + ns = irtl_ns_units[(irtl >> 10) & 0x3]; return div64_u64((irtl & 0x3FF) * ns, 1000); @@ -1200,43 +1203,39 @@ static unsigned long long irtl_2_usec(unsigned long long irtl) static void bxt_idle_state_table_update(void) { unsigned long long msr; + unsigned int usec; rdmsrl(MSR_PKGC6_IRTL, msr); - if (msr) { - unsigned int usec = irtl_2_usec(msr); - + usec = irtl_2_usec(msr); + if (usec) { bxt_cstates[2].exit_latency = usec; bxt_cstates[2].target_residency = usec; } rdmsrl(MSR_PKGC7_IRTL, msr); - if (msr) { - unsigned int usec = irtl_2_usec(msr); - + usec = irtl_2_usec(msr); + if (usec) { bxt_cstates[3].exit_latency = usec; bxt_cstates[3].target_residency = usec; } rdmsrl(MSR_PKGC8_IRTL, msr); - if (msr) { - unsigned int usec = irtl_2_usec(msr); - + usec = irtl_2_usec(msr); + if (usec) { bxt_cstates[4].exit_latency = usec; bxt_cstates[4].target_residency = usec; } rdmsrl(MSR_PKGC9_IRTL, msr); - if (msr) { - unsigned int usec = irtl_2_usec(msr); - + usec = irtl_2_usec(msr); + if (usec) { bxt_cstates[5].exit_latency = usec; bxt_cstates[5].target_residency = usec; } rdmsrl(MSR_PKGC10_IRTL, msr); - if (msr) { - unsigned int usec = irtl_2_usec(msr); - + usec = irtl_2_usec(msr); + if (usec) { bxt_cstates[6].exit_latency = usec; bxt_cstates[6].target_residency = usec; } -- cgit v0.10.2 From bef450962597ff39a7f9d53a30523aae9eb55843 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Mon, 27 Jun 2016 00:35:48 -0600 Subject: intel_idle: correct BXT support Commit 5dcef69486 ("intel_idle: add BXT support") added an 8-element lookup array with just a 2-bit value used for lookups. As per the SDM that bit field is really 3 bits wide. While this is supposedly benign here, future re-use of the code for other CPUs might expose the issue. Signed-off-by: Jan Beulich Signed-off-by: Rafael J. Wysocki diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 5300f25..9b2ef24 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -1190,7 +1190,7 @@ static unsigned long long irtl_2_usec(unsigned long long irtl) if (!irtl) return 0; - ns = irtl_ns_units[(irtl >> 10) & 0x3]; + ns = irtl_ns_units[(irtl >> 10) & 0x7]; return div64_u64((irtl & 0x3FF) * ns, 1000); } -- cgit v0.10.2