Michal Suchanek 8ea1dc
From 7ded429152e84831f6696585755f318fb351e67f Mon Sep 17 00:00:00 2001
Michal Suchanek 8ea1dc
From: Nicholas Piggin <npiggin@gmail.com>
Michal Suchanek 8ea1dc
Date: Wed, 14 Jun 2017 23:02:41 +1000
Michal Suchanek 8ea1dc
Subject: [PATCH] cpuidle: powerpc: no memory barrier after break from idle
Michal Suchanek 8ea1dc
Michal Suchanek 8ea1dc
References: PED-3947 bsc#1210544 ltc#202303
Michal Suchanek 8ea1dc
Patch-mainline: v4.13-rc1
Michal Suchanek 8ea1dc
Git-commit: 7ded429152e84831f6696585755f318fb351e67f
Michal Suchanek 8ea1dc
Michal Suchanek 8ea1dc
A memory barrier is not required after the task wakes up,
Michal Suchanek 8ea1dc
only if we clear the polling flag before waking. The case
Michal Suchanek 8ea1dc
where we have work to do is the important one, so optimise
Michal Suchanek 8ea1dc
for it.
Michal Suchanek 8ea1dc
Michal Suchanek 8ea1dc
Reviewed-by: Vaidyanathan Srinivasan <svaidy@linux.vnet.ibm.com>
Michal Suchanek 8ea1dc
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Michal Suchanek 8ea1dc
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Michal Suchanek 8ea1dc
Acked-by: Michal Suchanek <msuchanek@suse.de>
Michal Suchanek 8ea1dc
---
Michal Suchanek 8ea1dc
 drivers/cpuidle/cpuidle-powernv.c | 11 +++++++++--
Michal Suchanek 8ea1dc
 drivers/cpuidle/cpuidle-pseries.c | 11 +++++++++--
Michal Suchanek 8ea1dc
 2 files changed, 18 insertions(+), 4 deletions(-)
Michal Suchanek 8ea1dc
Michal Suchanek 8ea1dc
diff --git a/drivers/cpuidle/cpuidle-powernv.c b/drivers/cpuidle/cpuidle-powernv.c
Michal Suchanek 8ea1dc
index 9d03326ac05e..37b0698b7193 100644
Michal Suchanek 8ea1dc
--- a/drivers/cpuidle/cpuidle-powernv.c
Michal Suchanek 8ea1dc
+++ b/drivers/cpuidle/cpuidle-powernv.c
Michal Suchanek 8ea1dc
@@ -59,14 +59,21 @@ static int snooze_loop(struct cpuidle_device *dev,
Michal Suchanek 8ea1dc
 	ppc64_runlatch_off();
Michal Suchanek 8ea1dc
 	HMT_very_low();
Michal Suchanek 8ea1dc
 	while (!need_resched()) {
Michal Suchanek 8ea1dc
-		if (likely(snooze_timeout_en) && get_tb() > snooze_exit_time)
Michal Suchanek 8ea1dc
+		if (likely(snooze_timeout_en) && get_tb() > snooze_exit_time) {
Michal Suchanek 8ea1dc
+			/*
Michal Suchanek 8ea1dc
+			 * Task has not woken up but we are exiting the polling
Michal Suchanek 8ea1dc
+			 * loop anyway. Require a barrier after polling is
Michal Suchanek 8ea1dc
+			 * cleared to order subsequent test of need_resched().
Michal Suchanek 8ea1dc
+			 */
Michal Suchanek 8ea1dc
+			clear_thread_flag(TIF_POLLING_NRFLAG);
Michal Suchanek 8ea1dc
+			smp_mb();
Michal Suchanek 8ea1dc
 			break;
Michal Suchanek 8ea1dc
+		}
Michal Suchanek 8ea1dc
 	}
Michal Suchanek 8ea1dc
 
Michal Suchanek 8ea1dc
 	HMT_medium();
Michal Suchanek 8ea1dc
 	ppc64_runlatch_on();
Michal Suchanek 8ea1dc
 	clear_thread_flag(TIF_POLLING_NRFLAG);
Michal Suchanek 8ea1dc
-	smp_mb();
Michal Suchanek 8ea1dc
 
Michal Suchanek 8ea1dc
 	return index;
Michal Suchanek 8ea1dc
 }
Michal Suchanek 8ea1dc
diff --git a/drivers/cpuidle/cpuidle-pseries.c b/drivers/cpuidle/cpuidle-pseries.c
Michal Suchanek 8ea1dc
index a404f352d284..e9b3853d93ea 100644
Michal Suchanek 8ea1dc
--- a/drivers/cpuidle/cpuidle-pseries.c
Michal Suchanek 8ea1dc
+++ b/drivers/cpuidle/cpuidle-pseries.c
Michal Suchanek 8ea1dc
@@ -71,13 +71,20 @@ static int snooze_loop(struct cpuidle_device *dev,
Michal Suchanek 8ea1dc
 	while (!need_resched()) {
Michal Suchanek 8ea1dc
 		HMT_low();
Michal Suchanek 8ea1dc
 		HMT_very_low();
Michal Suchanek 8ea1dc
-		if (snooze_timeout_en && get_tb() > snooze_exit_time)
Michal Suchanek 8ea1dc
+		if (likely(snooze_timeout_en) && get_tb() > snooze_exit_time) {
Michal Suchanek 8ea1dc
+			/*
Michal Suchanek 8ea1dc
+			 * Task has not woken up but we are exiting the polling
Michal Suchanek 8ea1dc
+			 * loop anyway. Require a barrier after polling is
Michal Suchanek 8ea1dc
+			 * cleared to order subsequent test of need_resched().
Michal Suchanek 8ea1dc
+			 */
Michal Suchanek 8ea1dc
+			clear_thread_flag(TIF_POLLING_NRFLAG);
Michal Suchanek 8ea1dc
+			smp_mb();
Michal Suchanek 8ea1dc
 			break;
Michal Suchanek 8ea1dc
+		}
Michal Suchanek 8ea1dc
 	}
Michal Suchanek 8ea1dc
 
Michal Suchanek 8ea1dc
 	HMT_medium();
Michal Suchanek 8ea1dc
 	clear_thread_flag(TIF_POLLING_NRFLAG);
Michal Suchanek 8ea1dc
-	smp_mb();
Michal Suchanek 8ea1dc
 
Michal Suchanek 8ea1dc
 	idle_loop_epilog(in_purr);
Michal Suchanek 8ea1dc
 
Michal Suchanek 8ea1dc
-- 
Michal Suchanek 8ea1dc
2.40.0
Michal Suchanek 8ea1dc