All of lore.kernel.org
 help / color / mirror / Atom feed
From: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
To: Sudeep Holla <sudeep.holla@arm.com>
Cc: linux-acpi@vger.kernel.org,
	"Rafael J. Wysocki" <rjw@rjwysocki.net>,
	linux-kernel@vger.kernel.org,
	Vikas Sajjan <vikas.cha.sajjan@hpe.com>, Sunil <sunil.vl@hpe.com>,
	Prashanth Prakash <pprakash@codeaurora.org>,
	Ashwin Chaugule <ashwin.chaugule@linaro.org>,
	Al Stone <al.stone@linaro.org>,
	Mark Rutland <mark.rutland@arm.com>,
	linux-arm-kernel@lists.infradead.org, daniel.lezcano@linaro.org,
	khilman@baylibre.com
Subject: Re: [PATCH v5 4/5] arm64: add support for ACPI Low Power Idle(LPI)
Date: Fri, 10 Jun 2016 13:50:28 +0100	[thread overview]
Message-ID: <20160610125028.GA24002@red-moon> (raw)
In-Reply-To: <1462981062-24909-5-git-send-email-sudeep.holla@arm.com>

[+ Daniel, Kevin]

On Wed, May 11, 2016 at 04:37:41PM +0100, Sudeep Holla wrote:
> This patch adds appropriate callbacks to support ACPI Low Power Idle
> (LPI) on ARM64.
> 
> Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Cc: linux-arm-kernel@lists.infradead.org
> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
> ---
>  arch/arm64/kernel/acpi.c | 48 +++++++++++++++++++++++++++++++++++++++++
>  drivers/firmware/psci.c  | 56 ++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 104 insertions(+)
> 
> diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c

I think we can add this to arm64/kernel/cpuidle.c so that we have all
arch code managing idle in one place.

> index d1ce8e2f98b9..bf82ce5c8fce 100644
> --- a/arch/arm64/kernel/acpi.c
> +++ b/arch/arm64/kernel/acpi.c
> @@ -18,6 +18,7 @@
>  #include <linux/acpi.h>
>  #include <linux/bootmem.h>
>  #include <linux/cpumask.h>
> +#include <linux/cpu_pm.h>
>  #include <linux/init.h>
>  #include <linux/irq.h>
>  #include <linux/irqdomain.h>
> @@ -25,6 +26,9 @@
>  #include <linux/of_fdt.h>
>  #include <linux/smp.h>
>  
> +#include <acpi/processor.h>
> +
> +#include <asm/cpuidle.h>
>  #include <asm/cputype.h>
>  #include <asm/cpu_ops.h>
>  #include <asm/smp_plat.h>
> @@ -211,6 +215,50 @@ void __init acpi_boot_table_init(void)
>  	}
>  }
>  
> +int acpi_processor_ffh_lpi_probe(unsigned int cpu)
> +{
> +	return arm_cpuidle_init(cpu);
> +}
> +
> +#define ACPI_FFH_LPI_ARM_FLAGS_CORE_CONTEXT	BIT(0)
> +#define ACPI_FFH_LPI_ARM_FLAGS_TRACE_CONTEXT	BIT(1)
> +#define ACPI_FFH_LPI_ARM_FLAGS_GICR_CONTEXT	BIT(2)
> +#define ACPI_FFH_LPI_ARM_FLAGS_GICD_CONTEXT	BIT(3)
> +#define ACPI_FFH_LPI_ARM_FLAGS_ALL_CONTEXT	\
> +	(ACPI_FFH_LPI_ARM_FLAGS_CORE_CONTEXT |	\
> +	 ACPI_FFH_LPI_ARM_FLAGS_TRACE_CONTEXT |	\
> +	 ACPI_FFH_LPI_ARM_FLAGS_GICR_CONTEXT |	\
> +	 ACPI_FFH_LPI_ARM_FLAGS_GICD_CONTEXT)
> +
> +struct acpi_lpi_state *lpi;
> +int acpi_processor_ffh_lpi_enter(struct acpi_lpi_state *lpi, int idx)
> +{
> +	int ret = 0;
> +	bool save_ctx = lpi->arch_flags & ACPI_FFH_LPI_ARM_FLAGS_ALL_CONTEXT;

I am not really that keen on this, as you know. Those flags are
there to say "save these components registers". I see the CPU PM
notifiers as a way to save/restore CPU peripheral state, but
they should *not* carry out any action that affects the power
state itself, that's down to the suspend finisher (eg PSCI),
because that's where the specific idle states are managed.

I agree we have no clue whatsoever on what we *really* need
to save/restore, but that's orthogonal to what you are solving
here.

See eg gic_cpu_if_down(). Do we call it from the GIC CPU PM notifier ?
No. We should not handle the same problem differently.

On top of that, we have no way to solve this problem for DT,
all I am saying is that it is ill-defined and given that LPI
is new I'd rather we got it right from the beginning.

I am open to suggestions here.

> +
> +	if (!idx) {
> +		cpu_do_idle();
> +		return idx;
> +	}
> +
> +	/* TODO cpu_pm_{enter,exit} can be done in generic code ? */
> +	if (save_ctx)
> +		ret = cpu_pm_enter();
> +	if (!ret) {
> +		/*
> +		 * Pass idle state index to cpu_suspend which in turn will
> +		 * call the CPU ops suspend protocol with idle index as a
> +		 * parameter.
> +		 */
> +		ret = arm_cpuidle_suspend(idx);
> +
> +		if (save_ctx)
> +			cpu_pm_exit();
> +	}
> +
> +	return ret ? -1 : idx;

The body of this function (if we remove save_ctx) is identical
to arm_enter_idle_state(), it would be nice if we found a way
where to put this code and share it with the ARM CPUidle driver,
but I am not too fussed about that either.

> +}
> +
>  #ifdef CONFIG_ACPI_APEI
>  pgprot_t arch_apei_get_mem_attribute(phys_addr_t addr)
>  {
> diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
> index fa4ea22ca12e..e06bfee68e1d 100644
> --- a/drivers/firmware/psci.c
> +++ b/drivers/firmware/psci.c
> @@ -13,6 +13,7 @@
>  
>  #define pr_fmt(fmt) "psci: " fmt
>  
> +#include <linux/acpi.h>
>  #include <linux/arm-smccc.h>
>  #include <linux/cpuidle.h>
>  #include <linux/errno.h>
> @@ -310,11 +311,66 @@ static int psci_dt_cpu_init_idle(struct device_node *cpu_node, int cpu)
>  	return ret;
>  }
>  
> +#ifdef CONFIG_ACPI
> +#include <acpi/processor.h>
> +
> +static int __maybe_unused psci_acpi_cpu_init_idle(unsigned int cpu)
> +{
> +	int i, count;
> +	u32 *psci_states;
> +	struct acpi_processor *pr;
> +	struct acpi_lpi_state *lpi;
> +
> +	pr = per_cpu(processors, cpu);
> +	if (unlikely(!pr || !pr->flags.has_lpi))
> +		return -EINVAL;
> +
> +	/*
> +	 * If the PSCI cpu_suspend function hook has not been initialized
> +	 * idle states must not be enabled, so bail out
> +	 */
> +	if (!psci_ops.cpu_suspend)
> +		return -EOPNOTSUPP;
> +
> +	count = pr->power.count - 1;

Nit: I am not sure this can happen, but you really do not want
count to become == -1.

> +	if (!count)
> +		return -ENODEV;
> +
> +	psci_states = kcalloc(count, sizeof(*psci_states), GFP_KERNEL);
> +	if (!psci_states)
> +		return -ENOMEM;
> +
> +	for (i = 0; i < count; i++) {
> +		u32 state;
> +
> +		lpi = &pr->power.lpi_states[i + 1];
> +		state = lpi->address & 0xFFFFFFFF;
> +		if (!psci_power_state_is_valid(state)) {
> +			pr_warn("Invalid PSCI power state %#x\n", state);
> +			kfree(psci_states);
> +			return -EINVAL;
> +		}
> +		psci_states[i] = state;
> +	}
> +	/* Idle states parsed correctly, initialize per-cpu pointer */
> +	per_cpu(psci_power_state, cpu) = psci_states;
> +	return 0;
> +}
> +#else
> +static int __maybe_unused psci_acpi_cpu_init_idle(unsigned int cpu)
> +{
> +	return -EINVAL;
> +}
> +#endif
> +
>  int psci_cpu_init_idle(unsigned int cpu)
>  {
>  	struct device_node *cpu_node;
>  	int ret;
>  
> +	if (!acpi_disabled)
> +		return psci_acpi_cpu_init_idle(cpu);
> +
>  	cpu_node = of_get_cpu_node(cpu, NULL);
>  	if (!cpu_node)
>  		return -ENODEV;

save_ctx notwithstanding the patch is fine, let's define what to
do with that, remainder of the code is ok.

Thanks,
Lorenzo

WARNING: multiple messages have this Message-ID (diff)
From: lorenzo.pieralisi@arm.com (Lorenzo Pieralisi)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v5 4/5] arm64: add support for ACPI Low Power Idle(LPI)
Date: Fri, 10 Jun 2016 13:50:28 +0100	[thread overview]
Message-ID: <20160610125028.GA24002@red-moon> (raw)
In-Reply-To: <1462981062-24909-5-git-send-email-sudeep.holla@arm.com>

[+ Daniel, Kevin]

On Wed, May 11, 2016 at 04:37:41PM +0100, Sudeep Holla wrote:
> This patch adds appropriate callbacks to support ACPI Low Power Idle
> (LPI) on ARM64.
> 
> Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Cc: linux-arm-kernel at lists.infradead.org
> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
> ---
>  arch/arm64/kernel/acpi.c | 48 +++++++++++++++++++++++++++++++++++++++++
>  drivers/firmware/psci.c  | 56 ++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 104 insertions(+)
> 
> diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c

I think we can add this to arm64/kernel/cpuidle.c so that we have all
arch code managing idle in one place.

> index d1ce8e2f98b9..bf82ce5c8fce 100644
> --- a/arch/arm64/kernel/acpi.c
> +++ b/arch/arm64/kernel/acpi.c
> @@ -18,6 +18,7 @@
>  #include <linux/acpi.h>
>  #include <linux/bootmem.h>
>  #include <linux/cpumask.h>
> +#include <linux/cpu_pm.h>
>  #include <linux/init.h>
>  #include <linux/irq.h>
>  #include <linux/irqdomain.h>
> @@ -25,6 +26,9 @@
>  #include <linux/of_fdt.h>
>  #include <linux/smp.h>
>  
> +#include <acpi/processor.h>
> +
> +#include <asm/cpuidle.h>
>  #include <asm/cputype.h>
>  #include <asm/cpu_ops.h>
>  #include <asm/smp_plat.h>
> @@ -211,6 +215,50 @@ void __init acpi_boot_table_init(void)
>  	}
>  }
>  
> +int acpi_processor_ffh_lpi_probe(unsigned int cpu)
> +{
> +	return arm_cpuidle_init(cpu);
> +}
> +
> +#define ACPI_FFH_LPI_ARM_FLAGS_CORE_CONTEXT	BIT(0)
> +#define ACPI_FFH_LPI_ARM_FLAGS_TRACE_CONTEXT	BIT(1)
> +#define ACPI_FFH_LPI_ARM_FLAGS_GICR_CONTEXT	BIT(2)
> +#define ACPI_FFH_LPI_ARM_FLAGS_GICD_CONTEXT	BIT(3)
> +#define ACPI_FFH_LPI_ARM_FLAGS_ALL_CONTEXT	\
> +	(ACPI_FFH_LPI_ARM_FLAGS_CORE_CONTEXT |	\
> +	 ACPI_FFH_LPI_ARM_FLAGS_TRACE_CONTEXT |	\
> +	 ACPI_FFH_LPI_ARM_FLAGS_GICR_CONTEXT |	\
> +	 ACPI_FFH_LPI_ARM_FLAGS_GICD_CONTEXT)
> +
> +struct acpi_lpi_state *lpi;
> +int acpi_processor_ffh_lpi_enter(struct acpi_lpi_state *lpi, int idx)
> +{
> +	int ret = 0;
> +	bool save_ctx = lpi->arch_flags & ACPI_FFH_LPI_ARM_FLAGS_ALL_CONTEXT;

I am not really that keen on this, as you know. Those flags are
there to say "save these components registers". I see the CPU PM
notifiers as a way to save/restore CPU peripheral state, but
they should *not* carry out any action that affects the power
state itself, that's down to the suspend finisher (eg PSCI),
because that's where the specific idle states are managed.

I agree we have no clue whatsoever on what we *really* need
to save/restore, but that's orthogonal to what you are solving
here.

See eg gic_cpu_if_down(). Do we call it from the GIC CPU PM notifier ?
No. We should not handle the same problem differently.

On top of that, we have no way to solve this problem for DT,
all I am saying is that it is ill-defined and given that LPI
is new I'd rather we got it right from the beginning.

I am open to suggestions here.

> +
> +	if (!idx) {
> +		cpu_do_idle();
> +		return idx;
> +	}
> +
> +	/* TODO cpu_pm_{enter,exit} can be done in generic code ? */
> +	if (save_ctx)
> +		ret = cpu_pm_enter();
> +	if (!ret) {
> +		/*
> +		 * Pass idle state index to cpu_suspend which in turn will
> +		 * call the CPU ops suspend protocol with idle index as a
> +		 * parameter.
> +		 */
> +		ret = arm_cpuidle_suspend(idx);
> +
> +		if (save_ctx)
> +			cpu_pm_exit();
> +	}
> +
> +	return ret ? -1 : idx;

The body of this function (if we remove save_ctx) is identical
to arm_enter_idle_state(), it would be nice if we found a way
where to put this code and share it with the ARM CPUidle driver,
but I am not too fussed about that either.

> +}
> +
>  #ifdef CONFIG_ACPI_APEI
>  pgprot_t arch_apei_get_mem_attribute(phys_addr_t addr)
>  {
> diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
> index fa4ea22ca12e..e06bfee68e1d 100644
> --- a/drivers/firmware/psci.c
> +++ b/drivers/firmware/psci.c
> @@ -13,6 +13,7 @@
>  
>  #define pr_fmt(fmt) "psci: " fmt
>  
> +#include <linux/acpi.h>
>  #include <linux/arm-smccc.h>
>  #include <linux/cpuidle.h>
>  #include <linux/errno.h>
> @@ -310,11 +311,66 @@ static int psci_dt_cpu_init_idle(struct device_node *cpu_node, int cpu)
>  	return ret;
>  }
>  
> +#ifdef CONFIG_ACPI
> +#include <acpi/processor.h>
> +
> +static int __maybe_unused psci_acpi_cpu_init_idle(unsigned int cpu)
> +{
> +	int i, count;
> +	u32 *psci_states;
> +	struct acpi_processor *pr;
> +	struct acpi_lpi_state *lpi;
> +
> +	pr = per_cpu(processors, cpu);
> +	if (unlikely(!pr || !pr->flags.has_lpi))
> +		return -EINVAL;
> +
> +	/*
> +	 * If the PSCI cpu_suspend function hook has not been initialized
> +	 * idle states must not be enabled, so bail out
> +	 */
> +	if (!psci_ops.cpu_suspend)
> +		return -EOPNOTSUPP;
> +
> +	count = pr->power.count - 1;

Nit: I am not sure this can happen, but you really do not want
count to become == -1.

> +	if (!count)
> +		return -ENODEV;
> +
> +	psci_states = kcalloc(count, sizeof(*psci_states), GFP_KERNEL);
> +	if (!psci_states)
> +		return -ENOMEM;
> +
> +	for (i = 0; i < count; i++) {
> +		u32 state;
> +
> +		lpi = &pr->power.lpi_states[i + 1];
> +		state = lpi->address & 0xFFFFFFFF;
> +		if (!psci_power_state_is_valid(state)) {
> +			pr_warn("Invalid PSCI power state %#x\n", state);
> +			kfree(psci_states);
> +			return -EINVAL;
> +		}
> +		psci_states[i] = state;
> +	}
> +	/* Idle states parsed correctly, initialize per-cpu pointer */
> +	per_cpu(psci_power_state, cpu) = psci_states;
> +	return 0;
> +}
> +#else
> +static int __maybe_unused psci_acpi_cpu_init_idle(unsigned int cpu)
> +{
> +	return -EINVAL;
> +}
> +#endif
> +
>  int psci_cpu_init_idle(unsigned int cpu)
>  {
>  	struct device_node *cpu_node;
>  	int ret;
>  
> +	if (!acpi_disabled)
> +		return psci_acpi_cpu_init_idle(cpu);
> +
>  	cpu_node = of_get_cpu_node(cpu, NULL);
>  	if (!cpu_node)
>  		return -ENODEV;

save_ctx notwithstanding the patch is fine, let's define what to
do with that, remainder of the code is ok.

Thanks,
Lorenzo

  reply	other threads:[~2016-06-10 12:50 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-05-11 15:37 [PATCH v5 0/5] ACPI / processor_idle: Add ACPI v6.0 LPI support Sudeep Holla
2016-05-11 15:37 ` [PATCH v5 1/5] ACPI / processor_idle: introduce ACPI_PROCESSOR_CSTATE Sudeep Holla
2016-05-11 15:37   ` Sudeep Holla
2016-05-11 16:23   ` Rafael J. Wysocki
2016-05-11 16:23     ` Rafael J. Wysocki
2016-05-11 16:57     ` Sudeep Holla
2016-05-11 16:57       ` Sudeep Holla
     [not found]   ` <CAJvTdKnJPZ9Nfib=CqBczMP4BERqfqAzeSR-+jjFOGZR51oVmg@mail.gmail.com>
2016-05-11 18:28     ` Len Brown
2016-05-11 18:28       ` Len Brown
2016-05-12  9:10       ` Sudeep Holla
2016-05-12  9:10         ` Sudeep Holla
2016-05-12 13:21   ` [UPDATE][PATCH v5] " Sudeep Holla
2016-05-11 15:37 ` [PATCH v5 2/5] ACPI / processor_idle: Add support for Low Power Idle(LPI) states Sudeep Holla
2016-05-17 17:46   ` Prakash, Prashanth
2016-05-18 17:37     ` Sudeep Holla
2016-05-18 19:13       ` Prakash, Prashanth
2016-05-19 13:26         ` Sudeep Holla
2016-06-10 17:38   ` Sudeep Holla
2016-06-13 21:05     ` Rafael J. Wysocki
2016-06-14 14:24       ` Sudeep Holla
2016-05-11 15:37 ` [PATCH v5 3/5] arm64: cpuidle: drop __init section marker to arm_cpuidle_init Sudeep Holla
2016-05-11 15:37   ` Sudeep Holla
2016-05-11 15:37 ` [PATCH v5 4/5] arm64: add support for ACPI Low Power Idle(LPI) Sudeep Holla
2016-05-11 15:37   ` Sudeep Holla
2016-06-10 12:50   ` Lorenzo Pieralisi [this message]
2016-06-10 12:50     ` Lorenzo Pieralisi
2016-06-13 16:27     ` Daniel Lezcano
2016-06-13 16:27       ` Daniel Lezcano
2016-06-13  4:47   ` Sajjan, Vikas C
2016-06-13  4:47     ` Sajjan, Vikas C
2016-06-13  9:40     ` Sudeep Holla
2016-06-13  9:40       ` Sudeep Holla
2016-05-11 15:37 ` [PATCH v5 5/5] ACPI : enable ACPI_PROCESSOR_IDLE on ARM64 Sudeep Holla
2016-05-11 15:37   ` Sudeep Holla

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=20160610125028.GA24002@red-moon \
    --to=lorenzo.pieralisi@arm.com \
    --cc=al.stone@linaro.org \
    --cc=ashwin.chaugule@linaro.org \
    --cc=daniel.lezcano@linaro.org \
    --cc=khilman@baylibre.com \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=pprakash@codeaurora.org \
    --cc=rjw@rjwysocki.net \
    --cc=sudeep.holla@arm.com \
    --cc=sunil.vl@hpe.com \
    --cc=vikas.cha.sajjan@hpe.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.