linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/13] intel_idle patches ready for upstream
@ 2016-04-06 21:00 Len Brown
  2016-04-06 21:00 ` [PATCH 01/13] intel_idle: add BXT support Len Brown
  0 siblings, 1 reply; 14+ messages in thread
From: Len Brown @ 2016-04-06 21:00 UTC (permalink / raw)
  To: linux-pm; +Cc: linux-kernel

Bug fixes, plus add a few more table entires for new model #'s.

Some of the BXT table entries will be replaced by values read
from processor configuration registers at boot-time.

Let me know if you see troubles with any of these patches.

They are all available on this git branch:

git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux.git cpuidle

thanks,
-Len Brown, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 01/13] intel_idle: add BXT support
  2016-04-06 21:00 [PATCH 0/13] intel_idle patches ready for upstream Len Brown
@ 2016-04-06 21:00 ` Len Brown
  2016-04-06 21:00   ` [PATCH 02/13] intel_idle: remove useless return from void function Len Brown
                     ` (11 more replies)
  0 siblings, 12 replies; 14+ messages in thread
From: Len Brown @ 2016-04-06 21:00 UTC (permalink / raw)
  To: linux-pm; +Cc: linux-kernel, Len Brown

From: Len Brown <len.brown@intel.com>

Broxton has all the HSW C-states, except C3.
BXT C-state timing is slightly different.

Here we trust the IRTL MSRs as authority
on maximum C-state latency, and override the driver's tables
with the values found in the associated IRTL MSRs.
Further we set the target_residency to 1x maximum latency,
trusting the hardware demotion logic.

Signed-off-by: Len Brown <len.brown@intel.com>
---
 arch/x86/include/asm/msr-index.h |   8 +++
 drivers/idle/intel_idle.c        | 137 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 145 insertions(+)

diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 2da46ac..1e81927 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -167,6 +167,14 @@
 #define MSR_PKG_C9_RESIDENCY		0x00000631
 #define MSR_PKG_C10_RESIDENCY		0x00000632
 
+/* Interrupt Response Limit */
+#define MSR_PKGC3_IRTL			0x0000060a
+#define MSR_PKGC6_IRTL			0x0000060b
+#define MSR_PKGC7_IRTL			0x0000060c
+#define MSR_PKGC8_IRTL			0x00000633
+#define MSR_PKGC9_IRTL			0x00000634
+#define MSR_PKGC10_IRTL			0x00000635
+
 /* Run Time Average Power Limiting (RAPL) Interface */
 
 #define MSR_RAPL_POWER_UNIT		0x00000606
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index ba947df..012980a 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -737,6 +737,67 @@ static struct cpuidle_state knl_cstates[] = {
 		.enter = NULL }
 };
 
+static struct cpuidle_state bxt_cstates[] = {
+	{
+		.name = "C1-BXT",
+		.desc = "MWAIT 0x00",
+		.flags = MWAIT2flg(0x00),
+		.exit_latency = 2,
+		.target_residency = 2,
+		.enter = &intel_idle,
+		.enter_freeze = intel_idle_freeze, },
+	{
+		.name = "C1E-BXT",
+		.desc = "MWAIT 0x01",
+		.flags = MWAIT2flg(0x01),
+		.exit_latency = 10,
+		.target_residency = 20,
+		.enter = &intel_idle,
+		.enter_freeze = intel_idle_freeze, },
+	{
+		.name = "C6-BXT",
+		.desc = "MWAIT 0x20",
+		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
+		.exit_latency = 133,
+		.target_residency = 133,
+		.enter = &intel_idle,
+		.enter_freeze = intel_idle_freeze, },
+	{
+		.name = "C7s-BXT",
+		.desc = "MWAIT 0x31",
+		.flags = MWAIT2flg(0x31) | CPUIDLE_FLAG_TLB_FLUSHED,
+		.exit_latency = 155,
+		.target_residency = 155,
+		.enter = &intel_idle,
+		.enter_freeze = intel_idle_freeze, },
+	{
+		.name = "C8-BXT",
+		.desc = "MWAIT 0x40",
+		.flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED,
+		.exit_latency = 1000,
+		.target_residency = 1000,
+		.enter = &intel_idle,
+		.enter_freeze = intel_idle_freeze, },
+	{
+		.name = "C9-BXT",
+		.desc = "MWAIT 0x50",
+		.flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED,
+		.exit_latency = 2000,
+		.target_residency = 2000,
+		.enter = &intel_idle,
+		.enter_freeze = intel_idle_freeze, },
+	{
+		.name = "C10-BXT",
+		.desc = "MWAIT 0x60",
+		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
+		.exit_latency = 10000,
+		.target_residency = 10000,
+		.enter = &intel_idle,
+		.enter_freeze = intel_idle_freeze, },
+	{
+		.enter = NULL }
+};
+
 /**
  * intel_idle
  * @dev: cpuidle_device
@@ -914,6 +975,11 @@ static const struct idle_cpu idle_cpu_knl = {
 	.state_table = knl_cstates,
 };
 
+static const struct idle_cpu idle_cpu_bxt = {
+	.state_table = bxt_cstates,
+	.disable_promotion_to_c1e = true,
+};
+
 #define ICPU(model, cpu) \
 	{ X86_VENDOR_INTEL, 6, model, X86_FEATURE_MWAIT, (unsigned long)&cpu }
 
@@ -946,6 +1012,7 @@ static const struct x86_cpu_id intel_idle_ids[] __initconst = {
 	ICPU(0x4e, idle_cpu_skl),
 	ICPU(0x5e, idle_cpu_skl),
 	ICPU(0x57, idle_cpu_knl),
+	ICPU(0x5c, idle_cpu_bxt),
 	{}
 };
 MODULE_DEVICE_TABLE(x86cpu, intel_idle_ids);
@@ -1046,6 +1113,73 @@ static void ivt_idle_state_table_update(void)
 
 	/* else, 1 and 2 socket systems use default ivt_cstates */
 }
+
+/*
+ * Translate IRTL (Interrupt Response Time Limit) MSR to usec
+ */
+
+static unsigned int irtl_ns_units[] = {
+	1, 32, 1024, 32768, 1048576, 33554432, 0, 0 };
+
+static unsigned long long irtl_2_usec(unsigned long long irtl)
+{
+	unsigned long long ns;
+
+	ns = irtl_ns_units[(irtl >> 10) & 0x3];
+
+	return div64_u64((irtl & 0x3FF) * ns, 1000);
+}
+/*
+ * bxt_idle_state_table_update(void)
+ *
+ * On BXT, we trust the IRTL to show the definitive maximum latency
+ * We use the same value for target_residency.
+ */
+static void bxt_idle_state_table_update(void)
+{
+	unsigned long long msr;
+
+	rdmsrl(MSR_PKGC6_IRTL, msr);
+	if (msr) {
+		unsigned int usec = irtl_2_usec(msr);
+
+		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);
+
+		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);
+
+		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);
+
+		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);
+
+		bxt_cstates[6].exit_latency = usec;
+		bxt_cstates[6].target_residency = usec;
+	}
+
+}
 /*
  * sklh_idle_state_table_update(void)
  *
@@ -1101,6 +1235,9 @@ static void intel_idle_state_table_update(void)
 	case 0x3e: /* IVT */
 		ivt_idle_state_table_update();
 		break;
+	case 0x5c: /* BXT */
+		bxt_idle_state_table_update();
+		break;
 	case 0x5e: /* SKL-H */
 		sklh_idle_state_table_update();
 		break;
-- 
2.8.0.rc4.16.g56331f8

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 02/13] intel_idle: remove useless return from void function.
  2016-04-06 21:00 ` [PATCH 01/13] intel_idle: add BXT support Len Brown
@ 2016-04-06 21:00   ` Len Brown
  2016-04-06 21:00   ` [PATCH 03/13] intel_idle: Fix a helper function's return value Len Brown
                     ` (10 subsequent siblings)
  11 siblings, 0 replies; 14+ messages in thread
From: Len Brown @ 2016-04-06 21:00 UTC (permalink / raw)
  To: linux-pm; +Cc: linux-kernel, Richard Cochran, Len Brown

From: Richard Cochran <rcochran@linutronix.de>

Signed-off-by: Richard Cochran <rcochran@linutronix.de>
Signed-off-by: Len Brown <len.brown@intel.com>
---
 drivers/idle/intel_idle.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index 012980a..6638a80 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -1397,8 +1397,6 @@ static void __exit intel_idle_exit(void)
 	__unregister_cpu_notifier(&cpu_hotplug_notifier);
 
 	cpu_notifier_register_done();
-
-	return;
 }
 
 module_init(intel_idle_init);
-- 
2.8.0.rc4.16.g56331f8

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 03/13] intel_idle: Fix a helper function's return value.
  2016-04-06 21:00 ` [PATCH 01/13] intel_idle: add BXT support Len Brown
  2016-04-06 21:00   ` [PATCH 02/13] intel_idle: remove useless return from void function Len Brown
@ 2016-04-06 21:00   ` Len Brown
  2016-04-06 21:00   ` [PATCH 04/13] intel_idle: Remove redundant initialization calls Len Brown
                     ` (9 subsequent siblings)
  11 siblings, 0 replies; 14+ messages in thread
From: Len Brown @ 2016-04-06 21:00 UTC (permalink / raw)
  To: linux-pm; +Cc: linux-kernel, Richard Cochran, Len Brown

From: Richard Cochran <rcochran@linutronix.de>

The function, intel_idle_cpuidle_driver_init, delivers no error codes
at all.  This patch changes the function to return 'void' instead of
returning zero.

Signed-off-by: Richard Cochran <rcochran@linutronix.de>
Signed-off-by: Len Brown <len.brown@intel.com>
---
 drivers/idle/intel_idle.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index 6638a80..d2e7baf 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -1248,7 +1248,7 @@ static void intel_idle_state_table_update(void)
  * intel_idle_cpuidle_driver_init()
  * allocate, initialize cpuidle_states
  */
-static int __init intel_idle_cpuidle_driver_init(void)
+static void __init intel_idle_cpuidle_driver_init(void)
 {
 	int cstate;
 	struct cpuidle_driver *drv = &intel_idle_driver;
@@ -1310,8 +1310,6 @@ static int __init intel_idle_cpuidle_driver_init(void)
 
 	if (icpu->disable_promotion_to_c1e)	/* each-cpu is redundant */
 		on_each_cpu(c1e_promotion_disable, NULL, 1);
-
-	return 0;
 }
 
 
-- 
2.8.0.rc4.16.g56331f8

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 04/13] intel_idle: Remove redundant initialization calls.
  2016-04-06 21:00 ` [PATCH 01/13] intel_idle: add BXT support Len Brown
  2016-04-06 21:00   ` [PATCH 02/13] intel_idle: remove useless return from void function Len Brown
  2016-04-06 21:00   ` [PATCH 03/13] intel_idle: Fix a helper function's return value Len Brown
@ 2016-04-06 21:00   ` Len Brown
  2016-04-06 21:00   ` [PATCH 05/13] intel_idle: Fix deallocation order on the driver exit path Len Brown
                     ` (8 subsequent siblings)
  11 siblings, 0 replies; 14+ messages in thread
From: Len Brown @ 2016-04-06 21:00 UTC (permalink / raw)
  To: linux-pm; +Cc: linux-kernel, Richard Cochran, Len Brown

From: Richard Cochran <rcochran@linutronix.de>

The function, intel_idle_cpuidle_driver_init, makes calls on each CPU
to auto_demotion_disable() and c1e_promotion_disable().  These calls
are redundant, as intel_idle_cpu_init() does the same calls just a bit
later on.  They are also premature, as the driver registration may yet
fail.

This patch removes the redundant code.

Signed-off-by: Richard Cochran <rcochran@linutronix.de>
Signed-off-by: Len Brown <len.brown@intel.com>
---
 drivers/idle/intel_idle.c | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index d2e7baf..c50859d 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -1300,16 +1300,10 @@ static void __init intel_idle_cpuidle_driver_init(void)
 		drv->state_count += 1;
 	}
 
-	if (icpu->auto_demotion_disable_flags)
-		on_each_cpu(auto_demotion_disable, NULL, 1);
-
 	if (icpu->byt_auto_demotion_disable_flag) {
 		wrmsrl(MSR_CC6_DEMOTION_POLICY_CONFIG, 0);
 		wrmsrl(MSR_MC6_DEMOTION_POLICY_CONFIG, 0);
 	}
-
-	if (icpu->disable_promotion_to_c1e)	/* each-cpu is redundant */
-		on_each_cpu(c1e_promotion_disable, NULL, 1);
 }
 
 
-- 
2.8.0.rc4.16.g56331f8

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 05/13] intel_idle: Fix deallocation order on the driver exit path.
  2016-04-06 21:00 ` [PATCH 01/13] intel_idle: add BXT support Len Brown
                     ` (2 preceding siblings ...)
  2016-04-06 21:00   ` [PATCH 04/13] intel_idle: Remove redundant initialization calls Len Brown
@ 2016-04-06 21:00   ` Len Brown
  2016-04-06 21:00   ` [PATCH 06/13] intel_idle: Fix dangling registration on error path Len Brown
                     ` (7 subsequent siblings)
  11 siblings, 0 replies; 14+ messages in thread
From: Len Brown @ 2016-04-06 21:00 UTC (permalink / raw)
  To: linux-pm; +Cc: linux-kernel, Richard Cochran, Len Brown

From: Richard Cochran <rcochran@linutronix.de>

In the module_exit() method, this driver first frees its per-CPU
pointer, then unregisters a callback making use of the pointer.
Furthermore, the function, intel_idle_cpuidle_devices_uninit, is racy
against CPU hot plugging as it calls for_each_online_cpu().

This patch corrects the issues by unregistering first on the exit path
while holding the hot plug lock.

Signed-off-by: Richard Cochran <rcochran@linutronix.de>
Signed-off-by: Len Brown <len.brown@intel.com>
---
 drivers/idle/intel_idle.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index c50859d..5b309e5 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -1379,16 +1379,16 @@ static int __init intel_idle_init(void)
 
 static void __exit intel_idle_exit(void)
 {
-	intel_idle_cpuidle_devices_uninit();
-	cpuidle_unregister_driver(&intel_idle_driver);
-
 	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);
+	intel_idle_cpuidle_devices_uninit();
 
 	cpu_notifier_register_done();
+
+	cpuidle_unregister_driver(&intel_idle_driver);
 }
 
 module_init(intel_idle_init);
-- 
2.8.0.rc4.16.g56331f8

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 06/13] intel_idle: Fix dangling registration on error path.
  2016-04-06 21:00 ` [PATCH 01/13] intel_idle: add BXT support Len Brown
                     ` (3 preceding siblings ...)
  2016-04-06 21:00   ` [PATCH 05/13] intel_idle: Fix deallocation order on the driver exit path Len Brown
@ 2016-04-06 21:00   ` Len Brown
  2016-04-06 21:00   ` [PATCH 07/13] intel_idle: Avoid a double free of the per-CPU data Len Brown
                     ` (6 subsequent siblings)
  11 siblings, 0 replies; 14+ messages in thread
From: Len Brown @ 2016-04-06 21:00 UTC (permalink / raw)
  To: linux-pm; +Cc: linux-kernel, Richard Cochran, Len Brown

From: Richard Cochran <rcochran@linutronix.de>

In the module_init() method, if the per-CPU allocation fails, then the
active cpuidle registration is not cleaned up.  This patch fixes the
issue by attempting the allocation before registration, and then
cleaning it up again on registration failure.

Signed-off-by: Richard Cochran <rcochran@linutronix.de>
Signed-off-by: Len Brown <len.brown@intel.com>
---
 drivers/idle/intel_idle.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index 5b309e5..085538a 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -1347,19 +1347,20 @@ static int __init intel_idle_init(void)
 	if (retval)
 		return retval;
 
+	intel_idle_cpuidle_devices = alloc_percpu(struct cpuidle_device);
+	if (intel_idle_cpuidle_devices == NULL)
+		return -ENOMEM;
+
 	intel_idle_cpuidle_driver_init();
 	retval = cpuidle_register_driver(&intel_idle_driver);
 	if (retval) {
 		struct cpuidle_driver *drv = cpuidle_get_driver();
 		printk(KERN_DEBUG PREFIX "intel_idle yielding to %s",
 			drv ? drv->name : "none");
+		free_percpu(intel_idle_cpuidle_devices);
 		return retval;
 	}
 
-	intel_idle_cpuidle_devices = alloc_percpu(struct cpuidle_device);
-	if (intel_idle_cpuidle_devices == NULL)
-		return -ENOMEM;
-
 	cpu_notifier_register_begin();
 
 	for_each_online_cpu(i) {
-- 
2.8.0.rc4.16.g56331f8

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 07/13] intel_idle: Avoid a double free of the per-CPU data.
  2016-04-06 21:00 ` [PATCH 01/13] intel_idle: add BXT support Len Brown
                     ` (4 preceding siblings ...)
  2016-04-06 21:00   ` [PATCH 06/13] intel_idle: Fix dangling registration on error path Len Brown
@ 2016-04-06 21:00   ` Len Brown
  2016-04-06 21:00   ` [PATCH 08/13] intel_idle: Setup the timer broadcast only on successful driver load Len Brown
                     ` (5 subsequent siblings)
  11 siblings, 0 replies; 14+ messages in thread
From: Len Brown @ 2016-04-06 21:00 UTC (permalink / raw)
  To: linux-pm; +Cc: linux-kernel, Richard Cochran, Len Brown

From: Richard Cochran <rcochran@linutronix.de>

The helper function, intel_idle_cpuidle_devices_uninit, frees the
globally allocated per-CPU data.  However, this function is invoked
from the hot plug notifier callback at a time when freeing that data
is not safe.

If the call to cpuidle_register_driver() should fail (say, due to lack
of memory), then the driver will free its per-CPU region.  On the
*next* CPU_ONLINE event, the driver will happily use the region again
and even free it again if the failure repeats.

This patch fixes the issue by moving the call to free_percpu() outside
of the helper function at the two call sites that actually need to
free the per-CPU data.

Signed-off-by: Richard Cochran <rcochran@linutronix.de>
Signed-off-by: Len Brown <len.brown@intel.com>
---
 drivers/idle/intel_idle.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index 085538a..04fe4df 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -1069,7 +1069,7 @@ static int __init intel_idle_probe(void)
 
 /*
  * intel_idle_cpuidle_devices_uninit()
- * unregister, free cpuidle_devices
+ * Unregisters the cpuidle devices.
  */
 static void intel_idle_cpuidle_devices_uninit(void)
 {
@@ -1080,9 +1080,6 @@ static void intel_idle_cpuidle_devices_uninit(void)
 		dev = per_cpu_ptr(intel_idle_cpuidle_devices, i);
 		cpuidle_unregister_device(dev);
 	}
-
-	free_percpu(intel_idle_cpuidle_devices);
-	return;
 }
 
 /*
@@ -1368,6 +1365,7 @@ static int __init intel_idle_init(void)
 		if (retval) {
 			cpu_notifier_register_done();
 			cpuidle_unregister_driver(&intel_idle_driver);
+			free_percpu(intel_idle_cpuidle_devices);
 			return retval;
 		}
 	}
@@ -1390,6 +1388,7 @@ static void __exit intel_idle_exit(void)
 	cpu_notifier_register_done();
 
 	cpuidle_unregister_driver(&intel_idle_driver);
+	free_percpu(intel_idle_cpuidle_devices);
 }
 
 module_init(intel_idle_init);
-- 
2.8.0.rc4.16.g56331f8

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 08/13] intel_idle: Setup the timer broadcast only on successful driver load.
  2016-04-06 21:00 ` [PATCH 01/13] intel_idle: add BXT support Len Brown
                     ` (5 preceding siblings ...)
  2016-04-06 21:00   ` [PATCH 07/13] intel_idle: Avoid a double free of the per-CPU data Len Brown
@ 2016-04-06 21:00   ` Len Brown
  2016-04-06 21:00   ` [PATCH 09/13] intel_idle: Don't overreact to a cpuidle registration failure Len Brown
                     ` (4 subsequent siblings)
  11 siblings, 0 replies; 14+ messages in thread
From: Len Brown @ 2016-04-06 21:00 UTC (permalink / raw)
  To: linux-pm; +Cc: linux-kernel, Richard Cochran, Len Brown

From: Richard Cochran <rcochran@linutronix.de>

This driver sets the broadcast tick quite early on during probe and does
not clean up again in cast of failure.  This patch moves the setup call
after the registration, placing the on_each_cpu() calls within the global
CPU lock region.

Signed-off-by: Richard Cochran <rcochran@linutronix.de>
Signed-off-by: Len Brown <len.brown@intel.com>
---
 drivers/idle/intel_idle.c | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index 04fe4df..b5e92dd 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -1054,16 +1054,9 @@ static int __init intel_idle_probe(void)
 	icpu = (const struct idle_cpu *)id->driver_data;
 	cpuidle_state_table = icpu->state_table;
 
-	if (boot_cpu_has(X86_FEATURE_ARAT))	/* Always Reliable APIC Timer */
-		lapic_timer_reliable_states = LAPIC_TIMER_ALWAYS_RELIABLE;
-	else
-		on_each_cpu(__setup_broadcast_timer, (void *)true, 1);
-
 	pr_debug(PREFIX "v" INTEL_IDLE_VERSION
 		" model 0x%X\n", boot_cpu_data.x86_model);
 
-	pr_debug(PREFIX "lapic_timer_reliable_states 0x%x\n",
-		lapic_timer_reliable_states);
 	return 0;
 }
 
@@ -1371,8 +1364,16 @@ static int __init intel_idle_init(void)
 	}
 	__register_cpu_notifier(&cpu_hotplug_notifier);
 
+	if (boot_cpu_has(X86_FEATURE_ARAT))	/* Always Reliable APIC Timer */
+		lapic_timer_reliable_states = LAPIC_TIMER_ALWAYS_RELIABLE;
+	else
+		on_each_cpu(__setup_broadcast_timer, (void *)true, 1);
+
 	cpu_notifier_register_done();
 
+	pr_debug(PREFIX "lapic_timer_reliable_states 0x%x\n",
+		lapic_timer_reliable_states);
+
 	return 0;
 }
 
-- 
2.8.0.rc4.16.g56331f8

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 09/13] intel_idle: Don't overreact to a cpuidle registration failure.
  2016-04-06 21:00 ` [PATCH 01/13] intel_idle: add BXT support Len Brown
                     ` (6 preceding siblings ...)
  2016-04-06 21:00   ` [PATCH 08/13] intel_idle: Setup the timer broadcast only on successful driver load Len Brown
@ 2016-04-06 21:00   ` Len Brown
  2016-04-06 21:00   ` [PATCH 10/13] intel_idle: Propagate hot plug errors Len Brown
                     ` (3 subsequent siblings)
  11 siblings, 0 replies; 14+ messages in thread
From: Len Brown @ 2016-04-06 21:00 UTC (permalink / raw)
  To: linux-pm; +Cc: linux-kernel, Richard Cochran, Len Brown

From: Richard Cochran <rcochran@linutronix.de>

The helper function, intel_idle_cpu_init, registers one new device
with the cpuidle layer.  If the registration should fail, that
function immediately calls intel_idle_cpuidle_devices_uninit() to
unregister every last CPU's device.  However, it makes no sense to do
so, when called from the hot plug notifier callback.

This patch moves the call to intel_idle_cpuidle_devices_uninit()
outside of the helper function to the one call site that actually
needs to perform the de-registrations.

Signed-off-by: Richard Cochran <rcochran@linutronix.de>
Signed-off-by: Len Brown <len.brown@intel.com>
---
 drivers/idle/intel_idle.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index b5e92dd..807be29 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -1312,7 +1312,6 @@ static int intel_idle_cpu_init(int cpu)
 
 	if (cpuidle_register_device(dev)) {
 		pr_debug(PREFIX "cpuidle_register_device %d failed!\n", cpu);
-		intel_idle_cpuidle_devices_uninit();
 		return -EIO;
 	}
 
@@ -1356,6 +1355,7 @@ static int __init intel_idle_init(void)
 	for_each_online_cpu(i) {
 		retval = intel_idle_cpu_init(i);
 		if (retval) {
+			intel_idle_cpuidle_devices_uninit();
 			cpu_notifier_register_done();
 			cpuidle_unregister_driver(&intel_idle_driver);
 			free_percpu(intel_idle_cpuidle_devices);
-- 
2.8.0.rc4.16.g56331f8

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 10/13] intel_idle: Propagate hot plug errors.
  2016-04-06 21:00 ` [PATCH 01/13] intel_idle: add BXT support Len Brown
                     ` (7 preceding siblings ...)
  2016-04-06 21:00   ` [PATCH 09/13] intel_idle: Don't overreact to a cpuidle registration failure Len Brown
@ 2016-04-06 21:00   ` Len Brown
  2016-04-06 21:00   ` [PATCH 11/13] intel_idle: Clean up all registered devices on exit Len Brown
                     ` (2 subsequent siblings)
  11 siblings, 0 replies; 14+ messages in thread
From: Len Brown @ 2016-04-06 21:00 UTC (permalink / raw)
  To: linux-pm; +Cc: linux-kernel, Richard Cochran, Len Brown

From: Richard Cochran <rcochran@linutronix.de>

If a cpuidle registration error occurs during the hot plug notifier
callback, we should really inform the hot plug machinery instead of
just ignoring the error.  This patch changes the callback to properly
return on error.

Signed-off-by: Richard Cochran <rcochran@linutronix.de>
Signed-off-by: Len Brown <len.brown@intel.com>
---
 drivers/idle/intel_idle.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index 807be29..45e93f4 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -879,8 +879,11 @@ static int cpu_hotplug_notify(struct notifier_block *n,
 		 * driver in this case
 		 */
 		dev = per_cpu_ptr(intel_idle_cpuidle_devices, hotcpu);
-		if (!dev->registered)
-			intel_idle_cpu_init(hotcpu);
+		if (dev->registered)
+			break;
+
+		if (intel_idle_cpu_init(hotcpu))
+			return NOTIFY_BAD;
 
 		break;
 	}
-- 
2.8.0.rc4.16.g56331f8

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 11/13] intel_idle: Clean up all registered devices on exit.
  2016-04-06 21:00 ` [PATCH 01/13] intel_idle: add BXT support Len Brown
                     ` (8 preceding siblings ...)
  2016-04-06 21:00   ` [PATCH 10/13] intel_idle: Propagate hot plug errors Len Brown
@ 2016-04-06 21:00   ` Len Brown
  2016-04-06 21:00   ` [PATCH 12/13] intel_idle: Add SKX support Len Brown
  2016-04-06 21:00   ` [PATCH 13/13] intel_idle: Add KBL support Len Brown
  11 siblings, 0 replies; 14+ messages in thread
From: Len Brown @ 2016-04-06 21:00 UTC (permalink / raw)
  To: linux-pm; +Cc: linux-kernel, Richard Cochran, Len Brown

From: Richard Cochran <rcochran@linutronix.de>

This driver registers cpuidle devices when a CPU comes online, but it
leaves the registrations in place when a CPU goes offline.  The module
exit code only unregisters the currently online CPUs, leaving the
devices for offline CPUs dangling.

This patch changes the driver to clean up all registrations on exit,
even those from CPUs that are offline.

Signed-off-by: Richard Cochran <rcochran@linutronix.de>
Signed-off-by: Len Brown <len.brown@intel.com>
---
 drivers/idle/intel_idle.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index 45e93f4..7575699 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -1382,12 +1382,19 @@ static int __init intel_idle_init(void)
 
 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);
-	intel_idle_cpuidle_devices_uninit();
+
+	for_each_possible_cpu(i) {
+		dev = per_cpu_ptr(intel_idle_cpuidle_devices, i);
+		cpuidle_unregister_device(dev);
+	}
 
 	cpu_notifier_register_done();
 
-- 
2.8.0.rc4.16.g56331f8

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 12/13] intel_idle: Add SKX support
  2016-04-06 21:00 ` [PATCH 01/13] intel_idle: add BXT support Len Brown
                     ` (9 preceding siblings ...)
  2016-04-06 21:00   ` [PATCH 11/13] intel_idle: Clean up all registered devices on exit Len Brown
@ 2016-04-06 21:00   ` Len Brown
  2016-04-06 21:00   ` [PATCH 13/13] intel_idle: Add KBL support Len Brown
  11 siblings, 0 replies; 14+ messages in thread
From: Len Brown @ 2016-04-06 21:00 UTC (permalink / raw)
  To: linux-pm; +Cc: linux-kernel, Len Brown

From: Len Brown <len.brown@intel.com>

SKX is similar to BDX

Signed-off-by: Len Brown <len.brown@intel.com>
---
 drivers/idle/intel_idle.c | 34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index 7575699..d0ec343 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -660,6 +660,35 @@ static struct cpuidle_state skl_cstates[] = {
 		.enter = NULL }
 };
 
+static struct cpuidle_state skx_cstates[] = {
+	{
+		.name = "C1-SKX",
+		.desc = "MWAIT 0x00",
+		.flags = MWAIT2flg(0x00),
+		.exit_latency = 2,
+		.target_residency = 2,
+		.enter = &intel_idle,
+		.enter_freeze = intel_idle_freeze, },
+	{
+		.name = "C1E-SKX",
+		.desc = "MWAIT 0x01",
+		.flags = MWAIT2flg(0x01),
+		.exit_latency = 10,
+		.target_residency = 20,
+		.enter = &intel_idle,
+		.enter_freeze = intel_idle_freeze, },
+	{
+		.name = "C6-SKX",
+		.desc = "MWAIT 0x20",
+		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
+		.exit_latency = 133,
+		.target_residency = 600,
+		.enter = &intel_idle,
+		.enter_freeze = intel_idle_freeze, },
+	{
+		.enter = NULL }
+};
+
 static struct cpuidle_state atom_cstates[] = {
 	{
 		.name = "C1E-ATM",
@@ -968,6 +997,10 @@ static const struct idle_cpu idle_cpu_skl = {
 	.disable_promotion_to_c1e = true,
 };
 
+static const struct idle_cpu idle_cpu_skx = {
+	.state_table = skx_cstates,
+	.disable_promotion_to_c1e = true,
+};
 
 static const struct idle_cpu idle_cpu_avn = {
 	.state_table = avn_cstates,
@@ -1014,6 +1047,7 @@ static const struct x86_cpu_id intel_idle_ids[] __initconst = {
 	ICPU(0x56, idle_cpu_bdw),
 	ICPU(0x4e, idle_cpu_skl),
 	ICPU(0x5e, idle_cpu_skl),
+	ICPU(0x55, idle_cpu_skx),
 	ICPU(0x57, idle_cpu_knl),
 	ICPU(0x5c, idle_cpu_bxt),
 	{}
-- 
2.8.0.rc4.16.g56331f8

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 13/13] intel_idle: Add KBL support
  2016-04-06 21:00 ` [PATCH 01/13] intel_idle: add BXT support Len Brown
                     ` (10 preceding siblings ...)
  2016-04-06 21:00   ` [PATCH 12/13] intel_idle: Add SKX support Len Brown
@ 2016-04-06 21:00   ` Len Brown
  11 siblings, 0 replies; 14+ messages in thread
From: Len Brown @ 2016-04-06 21:00 UTC (permalink / raw)
  To: linux-pm; +Cc: linux-kernel, Len Brown

From: Len Brown <len.brown@intel.com>

KBL is similar to SKL

Signed-off-by: Len Brown <len.brown@intel.com>
---
 drivers/idle/intel_idle.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index d0ec343..c966492 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -1047,6 +1047,8 @@ static const struct x86_cpu_id intel_idle_ids[] __initconst = {
 	ICPU(0x56, idle_cpu_bdw),
 	ICPU(0x4e, idle_cpu_skl),
 	ICPU(0x5e, idle_cpu_skl),
+	ICPU(0x8e, idle_cpu_skl),
+	ICPU(0x9e, idle_cpu_skl),
 	ICPU(0x55, idle_cpu_skx),
 	ICPU(0x57, idle_cpu_knl),
 	ICPU(0x5c, idle_cpu_bxt),
-- 
2.8.0.rc4.16.g56331f8

^ permalink raw reply related	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2016-04-06 21:04 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-04-06 21:00 [PATCH 0/13] intel_idle patches ready for upstream Len Brown
2016-04-06 21:00 ` [PATCH 01/13] intel_idle: add BXT support Len Brown
2016-04-06 21:00   ` [PATCH 02/13] intel_idle: remove useless return from void function Len Brown
2016-04-06 21:00   ` [PATCH 03/13] intel_idle: Fix a helper function's return value Len Brown
2016-04-06 21:00   ` [PATCH 04/13] intel_idle: Remove redundant initialization calls Len Brown
2016-04-06 21:00   ` [PATCH 05/13] intel_idle: Fix deallocation order on the driver exit path Len Brown
2016-04-06 21:00   ` [PATCH 06/13] intel_idle: Fix dangling registration on error path Len Brown
2016-04-06 21:00   ` [PATCH 07/13] intel_idle: Avoid a double free of the per-CPU data Len Brown
2016-04-06 21:00   ` [PATCH 08/13] intel_idle: Setup the timer broadcast only on successful driver load Len Brown
2016-04-06 21:00   ` [PATCH 09/13] intel_idle: Don't overreact to a cpuidle registration failure Len Brown
2016-04-06 21:00   ` [PATCH 10/13] intel_idle: Propagate hot plug errors Len Brown
2016-04-06 21:00   ` [PATCH 11/13] intel_idle: Clean up all registered devices on exit Len Brown
2016-04-06 21:00   ` [PATCH 12/13] intel_idle: Add SKX support Len Brown
2016-04-06 21:00   ` [PATCH 13/13] intel_idle: Add KBL support Len Brown

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).