Received: by 2002:a05:6a10:206:0:0:0:0 with SMTP id 6csp841659pxj; Thu, 20 May 2021 23:52:15 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxAPI44AhgPvdYlKqo/XHzVwUImBjVTA/IAf1FnljkFQ+ztGJEBfOLpOtLbVIMp2udXyw9z X-Received: by 2002:a17:906:dfe9:: with SMTP id lc9mr8488356ejc.62.1621579934956; Thu, 20 May 2021 23:52:14 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1621579934; cv=none; d=google.com; s=arc-20160816; b=pbILwikKUaLMvFRPXHRZnWK98rEG505kIw1nt1Q5BLQjTPsE/tRiPZk6eec8dRBK0c X+JNfh4bURXzJixXpuTo9KU6BZqDcpw1+ntJuTB2pO+gxiWkHMyMy/D3EKQa/nITI3af mKIoed4bOaDu4So/e8PvMLfWT3hv22rsta7/hT87yq1PvVMhOMpmJfODvXVW45q9/pqp YP/Ym968BBgxZjTB46aHBd0nUhAGxwEYyja7mV1DAdCypc0yvYQaYIOpacOTLT5ehBHZ ghq65KuJRXun96WT0pKWN5vwyzNmFaz/erw6Nk6ja2UZReL2wCjcqoTmnaXGiAISGpAI UdOA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=uRG4gelGTu33BHMfq016RYRBpJp7Ja0MBBjAPXQEnp0=; b=WBXU7hDex7YsZrdVy0cUE/d7SyRuT9YkVc2/wI9M5I5+DCUjcvgChTeaLrD7IMUS5U bseRIc/3cUFT6cscooFz68jA+7eKvSv+pHbM8vqyqeR41vJ7nZeUcJeH7Hp4kbwWoye1 jQZ3KQK22A61AI1IMcwBiuDbF90Lt6J37kdbg8jhrtYoZtRULx8uZLHLy7Mb/sWgwiEb +3mFTABQlFytBhJPhNKGSmkvCO19jGbZNzrCSio4Lf+cHkANA4QQwjgArVRSsp2Zls7B 0lh4YCF1GnQa9rFvGgMFIImuotsNLAw4xrPEivkUvqW48x+K0NkY4l0VNocAmeA3CmRW EsnA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=Sdx2dYon; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id c14si4317744edv.258.2021.05.20.23.51.51; Thu, 20 May 2021 23:52:14 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=Sdx2dYon; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236206AbhETStB (ORCPT + 99 others); Thu, 20 May 2021 14:49:01 -0400 Received: from mail.kernel.org ([198.145.29.99]:39482 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236139AbhETSsw (ORCPT ); Thu, 20 May 2021 14:48:52 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 7259B61355; Thu, 20 May 2021 18:47:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1621536451; bh=2qJHn0NYcRsiDGsS+gVNRop9M5cOLWda5mJZcN1WsXc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Sdx2dYon4xoRVs0Hz9wbxFz/wOK1BTycjLW9cBydCYtm/VH0eAyZG6m3En+vo1Yf3 lo6laU2hralBSiIMoHmfqZuDOaqL53t4nBs5tjyonbHm6GvAzPI1pZmaYqmn1N4G/t v5nZhCozGEs9wRc358hWiwS3J6cEHWeOMKg0oQZ3kLmNVDyrM4QqjHYiqk97sTN7a8 GDd5AVdlecdpFocPg0vtdwCa+ge0mVFobtxpJjUYMElVFqnLDo7S0WPQGsglQS296M GDrdxgKpVKo3ldBHnyi3PdUsZyMO3ocQ5MDkf0uIpb9AndExtM3kv5RAOIGyF0+rIm yPNCEg//JrvWA== From: Will Deacon To: linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org, Will Deacon , Frederic Weisbecker , Thomas Gleixner , Marc Zyngier , Lorenzo Colitti , John Stultz , Stephen Boyd , kernel-team@android.com Subject: [PATCH 4/5] tick/broadcast: Program wakeup timer when entering idle if required Date: Thu, 20 May 2021 19:47:04 +0100 Message-Id: <20210520184705.10845-5-will@kernel.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20210520184705.10845-1-will@kernel.org> References: <20210520184705.10845-1-will@kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org When configuring the broadcast timer on entry to and exit from deep idle states, prefer a per-CPU wakeup timer if one exists. On entry to idle, stop the tick device and transfer the next event into the oneshot wakeup device, which will serve as the wakeup from idle. To avoid the overhead of additional hardware accesses on exit from idle, leave the timer armed and treat the inevitable interrupt as a (possibly spurious) tick event. Cc: Frederic Weisbecker Cc: Thomas Gleixner Cc: Marc Zyngier Cc: Lorenzo Colitti Cc: John Stultz Cc: Stephen Boyd Signed-off-by: Will Deacon --- kernel/time/tick-broadcast.c | 38 +++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index 8bd8cd69c8c9..ba5264e210d9 100644 --- a/kernel/time/tick-broadcast.c +++ b/kernel/time/tick-broadcast.c @@ -96,6 +96,15 @@ static struct clock_event_device *tick_get_oneshot_wakeup_device(int cpu) return per_cpu(tick_oneshot_wakeup_device, cpu); } +static void tick_oneshot_wakeup_handler(struct clock_event_device *wd) +{ + /* + * If we woke up early and the tick was reprogrammed in the + * meantime then this may be spurious but harmless. + */ + tick_receive_broadcast(); +} + static bool tick_set_oneshot_wakeup_device(struct clock_event_device *newdev, int cpu) { @@ -116,6 +125,7 @@ static bool tick_set_oneshot_wakeup_device(struct clock_event_device *newdev, if (curdev && newdev->rating <= curdev->rating) return false; + newdev->event_handler = tick_oneshot_wakeup_handler; set_device: per_cpu(tick_oneshot_wakeup_device, cpu) = newdev; return true; @@ -903,16 +913,42 @@ static int ___tick_broadcast_oneshot_control(enum tick_broadcast_state state, return ret; } +static int tick_oneshot_wakeup_control(enum tick_broadcast_state state, + struct tick_device *td, + int cpu) +{ + struct clock_event_device *dev, *wd; + + dev = td->evtdev; + if (td->mode != TICKDEV_MODE_ONESHOT) + return -EINVAL; + + wd = tick_get_oneshot_wakeup_device(cpu); + if (!wd) + return -ENODEV; + + if (state == TICK_BROADCAST_ENTER) { + clockevents_switch_state(dev, CLOCK_EVT_STATE_ONESHOT_STOPPED); + clockevents_switch_state(wd, CLOCK_EVT_STATE_ONESHOT); + clockevents_program_event(wd, dev->next_event, 1); + } + + return 0; +} + int __tick_broadcast_oneshot_control(enum tick_broadcast_state state) { struct tick_device *td = this_cpu_ptr(&tick_cpu_device); int cpu = smp_processor_id(); + if (!tick_oneshot_wakeup_control(state, td, cpu)) + return 0; + if (tick_broadcast_device.evtdev) return ___tick_broadcast_oneshot_control(state, td, cpu); /* - * If there is no broadcast device, tell the caller not + * If there is no broadcast or wakeup device, tell the caller not * to go into deep idle. */ return -EBUSY; -- 2.31.1.818.g46aad6cb9e-goog