From patchwork Wed Mar 6 11:18:36 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Gleixner X-Patchwork-Id: 2224721 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork2.kernel.org (Postfix) with ESMTP id 4F9BCDF23A for ; Wed, 6 Mar 2013 11:27:10 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1UDCRP-0001FN-NW; Wed, 06 Mar 2013 11:23:25 +0000 Received: from www.linutronix.de ([62.245.132.108] helo=Galois.linutronix.de) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UDCOl-0007zh-R9 for linux-arm-kernel@lists.infradead.org; Wed, 06 Mar 2013 11:20:50 +0000 Received: from localhost ([127.0.0.1] helo=localhost6.localdomain6) by Galois.linutronix.de with esmtp (Exim 4.72) (envelope-from ) id 1UDCMm-0006Mk-VR; Wed, 06 Mar 2013 12:18:37 +0100 Message-Id: <20130306111537.565418308@linutronix.de> User-Agent: quilt/0.48-1 Date: Wed, 06 Mar 2013 11:18:36 -0000 From: Thomas Gleixner To: LKML Subject: [patch 5/7] tick: Provide a check for a forced broadcast pending References: <20130306111351.883117670@linutronix.de> Content-Disposition: inline; filename=tick-provide-check-for-forced-broadcast-pending.patch X-Linutronix-Spam-Score: -1.0 X-Linutronix-Spam-Level: - X-Linutronix-Spam-Status: No , -1.0 points, 5.0 required, ALL_TRUSTED=-1, SHORTCIRCUIT=-0.0001 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130306_062040_319669_024E3C9E X-CRM114-Status: UNSURE ( 9.52 ) X-CRM114-Notice: Please train this message. X-Spam-Score: -4.8 (----) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-4.8 points) pts rule name description ---- ---------------------- -------------------------------------------------- -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at http://www.dnswl.org/, medium trust [62.245.132.108 listed in list.dnswl.org] -0.6 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: Lorenzo Pieralisi , Santosh Shilimkar , Jason Liu , John Stultz , LAK , Arjan van de Veen X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org On the CPU which gets woken along with the target CPU of the broadcast the following happens: deep_idle() <-- spurious wakeup broadcast_exit() set forced bit enable interrupts <-- Nothing happens disable interrupts broadcast_enter() <-- Here we observe the forced bit is set deep_idle() Now after that the target CPU of the broadcast runs the broadcast handler and finds the other CPU in both the broadcast and the forced mask, sends the IPI and stuff gets back to normal. So it's not actually harmful, just more evidence for the theory, that hardware designers have access to very special drug supplies. Now there is no point in going back to deep idle just to wake up again right away via an IPI. Provide a check which allows the idle code to avoid the deep idle transition. Signed-off-by: Thomas Gleixner --- include/linux/clockchips.h | 6 ++++++ kernel/time/tick-broadcast.c | 12 ++++++++++++ 2 files changed, 18 insertions(+) Index: tip/include/linux/clockchips.h =================================================================== --- tip.orig/include/linux/clockchips.h +++ tip/include/linux/clockchips.h @@ -170,6 +170,12 @@ extern void tick_broadcast(const struct extern int tick_receive_broadcast(void); #endif +#if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) && defined(CONFIG_TICK_ONESHOT) +extern int tick_check_broadcast_expired(void); +#else +static inline int tick_check_broadcast_expired(void) { return 0; } +#endif + #ifdef CONFIG_GENERIC_CLOCKEVENTS extern void clockevents_notify(unsigned long reason, void *arg); #else Index: tip/kernel/time/tick-broadcast.c =================================================================== --- tip.orig/kernel/time/tick-broadcast.c +++ tip/kernel/time/tick-broadcast.c @@ -413,6 +413,18 @@ static int tick_broadcast_set_event(ktim return clockevents_program_event(bc, expires, force); } +/* + * Called before going idle with interrupts disabled. Checks whether a + * broadcast event from the other core is about to happen. We detected + * that in tick_broadcast_oneshot_control(). The callsite can use this + * to avoid a deep idle transition as we are about to get the + * broadcast IPI right away. + */ +int tick_check_broadcast_expired(void) +{ + return cpumask_test_cpu(smp_processor_id(), tick_broadcast_force_mask); +} + int tick_resume_broadcast_oneshot(struct clock_event_device *bc) { clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);