From: "Pallipadi, Venkatesh" <venkatesh.pallipadi@intel.com>
To: "Zhao, Yakui" <yakui.zhao@intel.com>
Cc: LenBrown <lenb@kernel.org>,
"linux-acpi@vger.kernel.org" <linux-acpi@vger.kernel.org>,
"Pallipadi, Venkatesh" <venkatesh.pallipadi@intel.com>
Subject: Re: [PATCH] : ACPI : Use clocksource to get the C-state time instead of ACPI PM timer
Date: Mon, 12 Jan 2009 14:09:42 -0800 [thread overview]
Message-ID: <20090112220941.GA1446@linux-os.sc.intel.com> (raw)
In-Reply-To: <1231744070.4026.56.camel@yakui_zhao.sh.intel.com>
Patch looks ok in general. However, I am wonderng whether we reall need
ktime_get() here or can we use getnstimeofday() directly. Using
getnstimeofday() should be cheaper, especially if we are doing frequent
calls from multiple CPUs on every idle enter/exit. And I don't think we
need to worry about monotonic clock from ktime here...
Thanks,
Venki
On Sun, Jan 11, 2009 at 11:07:50PM -0800, Zhao, Yakui wrote:
> Subject: ACPI: Use clocksource to get the C-state time instead of ACPI PM timer
> From: Zhao Yakui <yakui.zhao@intel.com>
>
> On most boxes the ACPI PM timer is 24-bit counter that runs on 3.579545MHz
> clock. In such case the max C-state sleep time should be less than 4687ms when
> it is used to record C2/C3 duration time.
> But on some boxes the max C-state sleep time is more than 4687ms. In such
> case the overflow happens and the C-state duration time can't be counted
> accurately.
> Use clocksource to get the C-state time instead of ACPI PM timer
>
> Signed-off-by: Yakui Zhao <yakui.zhao@intel.com>
> Signed-off-by: Alexs Shi <alex.shi@intel.com>
> Signed-off-by: Shaohua Li <shaohua.li@intel.com>
> ---
> drivers/acpi/processor_idle.c | 68 +++++++++++++++++++++++++-----------------
> 1 file changed, 42 insertions(+), 26 deletions(-)
>
> Index: linux-2.6/drivers/acpi/processor_idle.c
> ===================================================================
> --- linux-2.6.orig/drivers/acpi/processor_idle.c
> +++ linux-2.6/drivers/acpi/processor_idle.c
> @@ -397,8 +397,8 @@ static void acpi_processor_idle(void)
> struct acpi_processor_cx *cx = NULL;
> struct acpi_processor_cx *next_state = NULL;
> int sleep_ticks = 0;
> - u32 t1, t2 = 0;
> -
> + ktime_t kt1, kt2;
> + u64 sleep_interval;
> /*
> * Interrupts must be disabled during bus mastering calculations and
> * for C2/C3 transitions.
> @@ -543,23 +543,26 @@ static void acpi_processor_idle(void)
> break;
>
> case ACPI_STATE_C2:
> - /* Get start time (ticks) */
> - t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
> + kt1 = ktime_get();
> /* Tell the scheduler that we are going deep-idle: */
> sched_clock_idle_sleep_event();
> /* Invoke C2 */
> acpi_state_timer_broadcast(pr, cx, 1);
> acpi_cstate_enter(cx);
> /* Get end time (ticks) */
> - t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
> -
> + kt2 = ktime_get();
> #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86)
> /* TSC halts in C2, so notify users */
> if (tsc_halts_in_c(ACPI_STATE_C2))
> mark_tsc_unstable("possible TSC halt in C2");
> #endif
> + /*
> + * Use the function of ktime_sub to get the time interval and
> + * then convert it to microsecond
> + */
> + sleep_interval = ktime_to_us(ktime_sub(kt2, kt1));
> /* Compute time (ticks) that we were actually asleep */
> - sleep_ticks = ticks_elapsed(t1, t2);
> + sleep_ticks = US_TO_PM_TIMER_TICKS(sleep_interval);
>
> /* Tell the scheduler how much we idled: */
> sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS);
> @@ -605,13 +608,13 @@ static void acpi_processor_idle(void)
> }
>
> /* Get start time (ticks) */
> - t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
> + kt1 = ktime_get();
> /* Invoke C3 */
> /* Tell the scheduler that we are going deep-idle: */
> sched_clock_idle_sleep_event();
> acpi_cstate_enter(cx);
> /* Get end time (ticks) */
> - t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
> + kt2 = ktime_get();
> if (pr->flags.bm_check && pr->flags.bm_control) {
> /* Enable bus master arbitration */
> atomic_dec(&c3_cpu_count);
> @@ -623,8 +626,13 @@ static void acpi_processor_idle(void)
> if (tsc_halts_in_c(ACPI_STATE_C3))
> mark_tsc_unstable("TSC halts in C3");
> #endif
> + /*
> + * Use the function of ktime_sub to get the time interval
> + * and convert it to microsecond.
> + */
> + sleep_interval = ktime_to_us(ktime_sub(kt2, kt1));
> /* Compute time (ticks) that we were actually asleep */
> - sleep_ticks = ticks_elapsed(t1, t2);
> + sleep_ticks = US_TO_PM_TIMER_TICKS(sleep_interval);
> /* Tell the scheduler how much we idled: */
> sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS);
>
> @@ -1455,7 +1463,8 @@ static inline void acpi_idle_do_entry(st
> static int acpi_idle_enter_c1(struct cpuidle_device *dev,
> struct cpuidle_state *state)
> {
> - u32 t1, t2;
> + ktime_t kt1, kt2;
> + u64 sleep_interval;
> struct acpi_processor *pr;
> struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
>
> @@ -1476,14 +1485,18 @@ static int acpi_idle_enter_c1(struct cpu
> if (pr->flags.bm_check)
> acpi_idle_update_bm_rld(pr, cx);
>
> - t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
> + kt1 = ktime_get();
> acpi_idle_do_entry(cx);
> - t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
> + kt2 = ktime_get();
>
> local_irq_enable();
> cx->usage++;
> -
> - return ticks_elapsed_in_us(t1, t2);
> + /*
> + * Use the ktime_sub to get the time interval and then convert
> + * it to microseconds
> + */
> + sleep_interval = ktime_to_us(ktime_sub(kt2, kt1));
> + return sleep_interval;
> }
>
> /**
> @@ -1496,7 +1509,8 @@ static int acpi_idle_enter_simple(struct
> {
> struct acpi_processor *pr;
> struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
> - u32 t1, t2;
> + ktime_t kt1, kt2;
> + u64 sleep_interval;
> int sleep_ticks = 0;
>
> pr = __get_cpu_var(processors);
> @@ -1533,18 +1547,19 @@ static int acpi_idle_enter_simple(struct
> if (cx->type == ACPI_STATE_C3)
> ACPI_FLUSH_CPU_CACHE();
>
> - t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
> + kt1 = ktime_get();
> /* Tell the scheduler that we are going deep-idle: */
> sched_clock_idle_sleep_event();
> acpi_idle_do_entry(cx);
> - t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
> + kt2 = ktime_get();
>
> #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86)
> /* TSC could halt in idle, so notify users */
> if (tsc_halts_in_c(cx->type))
> mark_tsc_unstable("TSC halts in idle");;
> #endif
> - sleep_ticks = ticks_elapsed(t1, t2);
> + sleep_interval = ktime_to_us(ktime_sub(kt2, kt1));
> + sleep_ticks = US_TO_PM_TIMER_TICKS(sleep_interval);
>
> /* Tell the scheduler how much we idled: */
> sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS);
> @@ -1556,7 +1571,7 @@ static int acpi_idle_enter_simple(struct
>
> acpi_state_timer_broadcast(pr, cx, 0);
> cx->time += sleep_ticks;
> - return ticks_elapsed_in_us(t1, t2);
> + return sleep_interval;
> }
>
> static int c3_cpu_count;
> @@ -1574,7 +1589,8 @@ static int acpi_idle_enter_bm(struct cpu
> {
> struct acpi_processor *pr;
> struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
> - u32 t1, t2;
> + ktime_t kt1, kt2;
> + u64 sleep_interval;
> int sleep_ticks = 0;
>
> pr = __get_cpu_var(processors);
> @@ -1643,10 +1659,9 @@ static int acpi_idle_enter_bm(struct cpu
> } else if (!pr->flags.bm_check) {
> ACPI_FLUSH_CPU_CACHE();
> }
> -
> - t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
> + kt1 = ktime_get();
> acpi_idle_do_entry(cx);
> - t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
> + kt2 = ktime_get();
>
> /* Re-enable bus master arbitration */
> if (pr->flags.bm_check && pr->flags.bm_control) {
> @@ -1661,7 +1676,8 @@ static int acpi_idle_enter_bm(struct cpu
> if (tsc_halts_in_c(ACPI_STATE_C3))
> mark_tsc_unstable("TSC halts in idle");
> #endif
> - sleep_ticks = ticks_elapsed(t1, t2);
> + sleep_interval = ktime_to_us(ktime_sub(kt2, kt1));
> + sleep_ticks = US_TO_PM_TIMER_TICKS(sleep_interval);
> /* Tell the scheduler how much we idled: */
> sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS);
>
> @@ -1672,7 +1688,7 @@ static int acpi_idle_enter_bm(struct cpu
>
> acpi_state_timer_broadcast(pr, cx, 0);
> cx->time += sleep_ticks;
> - return ticks_elapsed_in_us(t1, t2);
> + return sleep_interval;
> }
>
> struct cpuidle_driver acpi_idle_driver = {
>
>
next prev parent reply other threads:[~2009-01-12 22:09 UTC|newest]
Thread overview: 37+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-10-31 18:42 [PATCH] ACPI: EC: clean up tmp variable before reuse Alexey Starikovskiy
2008-11-03 8:02 ` Zhao Yakui
2008-11-03 8:24 ` [PATCH]: ACPI: Initialize EC global lock based on the return value of _GLK Zhao Yakui
2008-11-04 7:41 ` [PATCH]: ACPI Cleanup :Initialize EC global lock based on the return status Zhao Yakui
2008-11-04 8:05 ` Alexey Starikovskiy
2008-11-04 8:58 ` Rafael J. Wysocki
2008-11-04 9:21 ` Alexey Starikovskiy
2008-11-04 9:37 ` Zhao Yakui
2008-11-04 9:38 ` Alexey Starikovskiy
2008-11-05 1:05 ` Zhao Yakui
2008-11-05 7:24 ` Alexey Starikovskiy
2008-12-17 8:55 ` [PATCH] : ACPI : Use RSDT instead of XSDT by adding boot option of "acpi=rsdt" Zhao Yakui
2009-01-09 6:35 ` Len Brown
2009-01-09 10:54 ` Thomas Renninger
2009-01-09 10:59 ` Len Brown
2009-01-09 12:16 ` Thomas Renninger
2009-01-09 12:34 ` Matthew Garrett
2009-01-12 14:13 ` Thomas Renninger
2009-01-12 14:16 ` Matthew Garrett
2009-01-12 22:17 ` Thomas Renninger
2009-01-12 23:38 ` Matthew Garrett
2009-01-09 10:58 ` Blacklist known broken machines to use the rsdt and enabled Cstates on R40e Thomas Renninger
2009-01-09 10:58 ` [PATCH 1/2] Blacklist known broken machines (ThinkPad R40e and R50e) to use rsdt instead xsdt Thomas Renninger
2009-01-09 10:58 ` [PATCH 2/2] R40e using rsdt (previous patch) makes all Cstates work -> remove blacklisting Thomas Renninger
2008-12-30 4:01 ` [PATCH] : ACPI : Add the MWAIT C-state mask to avoid overflow Zhao Yakui
2009-01-04 4:04 ` Zhao Yakui
2009-01-09 6:28 ` Len Brown
2009-01-12 7:07 ` [PATCH] : ACPI : Use clocksource to get the C-state time instead of ACPI PM timer Zhao Yakui
2009-01-12 7:58 ` Rafael J. Wysocki
2009-01-12 9:31 ` Zhao Yakui
2009-01-12 12:27 ` Rafael J. Wysocki
2009-01-12 9:39 ` Zhao Yakui
2009-01-12 22:09 ` Pallipadi, Venkatesh [this message]
2009-01-13 1:26 ` Zhao Yakui
2009-01-13 1:42 ` Zhao Yakui
2009-01-13 3:50 ` [RESEND] " Zhao Yakui
2009-01-20 2:52 ` Len Brown
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20090112220941.GA1446@linux-os.sc.intel.com \
--to=venkatesh.pallipadi@intel.com \
--cc=lenb@kernel.org \
--cc=linux-acpi@vger.kernel.org \
--cc=yakui.zhao@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox