Re: [PATCH v6 4/5] arm64: add support for ACPI Low Power Idle(LPI)

2016-06-27 Thread Sudeep Holla



On 27/06/16 18:07, Sudeep Holla wrote:



On 27/06/16 17:29, Daniel Lezcano wrote:


[...]



acpi_disabled - acpi_disabled - acpi_disabled everywhere :/

The enable-method approach is not straightforward and now it is polluted
by acpi-disabled.

So IIUC,

smp_init_cpus (contains acpi_disabled)
   smp_cpu_setup
 cpu_read_ops
   cpu_read_enable_method (contains acpi_disabled)
 acpi_get_enable_method (returns 'psci' after checking
psci_is_present)

Then psci_cpu_init_idle is called... and check again acpi_disabled.

IMO, the circumlocution with the psci vs acpi vs acpi_disabled is
getting unnecessary too complex, is prone to error and will lead to
unmaintainable code very soon.

I suggest to sort out encapsulation and self-contained code before
adding more feature in this area.



I understand your concern but I have no idea on how to clean up. Lorenzo
asked to factor our common code between psci_{dt,acpi}_cpu_init_idle and
I think you might not like the refactoring[1]. I didn't want to change
cpuidle_ops and hence psci_dt_cpu_init_idle parameters. I will see if
changing that simplifies things.



One of the reasons for adding acpi_disabled check is to keep the other
logic at the same place. Otherwise we end up duplicating that code which
is what I have done in psci_{dt,acpi}_cpu_init_idle at the first place.

--
Regards,
Sudeep


Re: [PATCH v6 4/5] arm64: add support for ACPI Low Power Idle(LPI)

2016-06-27 Thread Sudeep Holla



On 27/06/16 17:29, Daniel Lezcano wrote:

On 06/22/2016 04:17 PM, Lorenzo Pieralisi wrote:

Hi Sudeep,

On Tue, Jun 14, 2016 at 03:48:38PM +0100, Sudeep Holla wrote:

This patch adds appropriate callbacks to support ACPI Low Power Idle
(LPI) on ARM64.

Now that arm_enter_idle_state is exactly same in both generic ARM{32,64}
CPUIdle driver and ARM64 backend for ACPI processor idle driver, we can
unify it and move to cpuidle-arm.h header.

Cc: Lorenzo Pieralisi 
Cc: Mark Rutland 
Cc: Daniel Lezcano 
Cc: "Rafael J. Wysocki" 
Cc: linux-arm-ker...@lists.infradead.org
Signed-off-by: Sudeep Holla 
---
  arch/arm64/kernel/cpuidle.c   | 17 +
  drivers/cpuidle/cpuidle-arm.c | 23 ++
  drivers/firmware/psci.c   | 56
+++
  include/linux/cpuidle-arm.h   | 30 +++
  4 files changed, 105 insertions(+), 21 deletions(-)
  create mode 100644 include/linux/cpuidle-arm.h


This patch seems fine by me, it would be good if Daniel can have
a look too.

Some minor comments below.

[...]


diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
index 03e04582791c..c6caa863d156 100644
--- a/drivers/firmware/psci.c
+++ b/drivers/firmware/psci.c
@@ -13,6 +13,7 @@

  #define pr_fmt(fmt) "psci: " fmt

+#include 
  #include 
  #include 
  #include 
@@ -310,11 +311,66 @@ static int psci_dt_cpu_init_idle(struct
device_node *cpu_node, int cpu)
  return ret;
  }

+#ifdef CONFIG_ACPI
+#include 
+
+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;
+if (count <= 0)
+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 & 0x;


Why mask 'address' if 'state' is u32 ?



Agreed, I overlooked it.


+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;


The ACPI and the PSCI code are not self contained here.

It would be nice to move this function to the ACPI code.


+}
+#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);
+


acpi_disabled - acpi_disabled - acpi_disabled everywhere :/

The enable-method approach is not straightforward and now it is polluted
by acpi-disabled.

So IIUC,

smp_init_cpus (contains acpi_disabled)
   smp_cpu_setup
 cpu_read_ops
   cpu_read_enable_method (contains acpi_disabled)
 acpi_get_enable_method (returns 'psci' after checking
psci_is_present)

Then psci_cpu_init_idle is called... and check again acpi_disabled.

IMO, the circumlocution with the psci vs acpi vs acpi_disabled is
getting unnecessary too complex, is prone to error and will lead to
unmaintainable code very soon.

I suggest to sort out encapsulation and self-contained code before
adding more feature in this area.



I understand your concern but I have no idea on how to clean up. Lorenzo
asked to factor our common code between psci_{dt,acpi}_cpu_init_idle and
I think you might not like the refactoring[1]. I didn't want to change
cpuidle_ops and hence psci_dt_cpu_init_idle parameters. I will see if
changing that simplifies things.


  cpu_node = of_get_cpu_node(cpu, NULL);
  if (!cpu_node)
  return -ENODEV;
diff --git a/include/linux/cpuidle-arm.h b/include/linux/cpuidle-arm.h
new file mode 100644
index ..b99bcb3f43dd
--- /dev/null
+++ b/include/linux/cpuidle-arm.h


arm-cpuidle.h for consistency with other (ARM) include/linux files ?


@@ -0,0 +1,30 @@
+#include 
+
+#include 
+
+/*
+ * arm_enter_idle_state - Programs CPU to enter the specified state
+ */
+static int arm_generic_enter_idle_state(int idx)
+{
+int ret;
+
+if (!idx) {
+cpu_do_idle();
+return idx;
+}
+
+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
+  

Re: [PATCH v6 4/5] arm64: add support for ACPI Low Power Idle(LPI)

2016-06-27 Thread Daniel Lezcano

On 06/22/2016 04:17 PM, Lorenzo Pieralisi wrote:

Hi Sudeep,

On Tue, Jun 14, 2016 at 03:48:38PM +0100, Sudeep Holla wrote:

This patch adds appropriate callbacks to support ACPI Low Power Idle
(LPI) on ARM64.

Now that arm_enter_idle_state is exactly same in both generic ARM{32,64}
CPUIdle driver and ARM64 backend for ACPI processor idle driver, we can
unify it and move to cpuidle-arm.h header.

Cc: Lorenzo Pieralisi 
Cc: Mark Rutland 
Cc: Daniel Lezcano 
Cc: "Rafael J. Wysocki" 
Cc: linux-arm-ker...@lists.infradead.org
Signed-off-by: Sudeep Holla 
---
  arch/arm64/kernel/cpuidle.c   | 17 +
  drivers/cpuidle/cpuidle-arm.c | 23 ++
  drivers/firmware/psci.c   | 56 +++
  include/linux/cpuidle-arm.h   | 30 +++
  4 files changed, 105 insertions(+), 21 deletions(-)
  create mode 100644 include/linux/cpuidle-arm.h


This patch seems fine by me, it would be good if Daniel can have
a look too.

Some minor comments below.

[...]


diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
index 03e04582791c..c6caa863d156 100644
--- a/drivers/firmware/psci.c
+++ b/drivers/firmware/psci.c
@@ -13,6 +13,7 @@

  #define pr_fmt(fmt) "psci: " fmt

+#include 
  #include 
  #include 
  #include 
@@ -310,11 +311,66 @@ static int psci_dt_cpu_init_idle(struct device_node 
*cpu_node, int cpu)
return ret;
  }

+#ifdef CONFIG_ACPI
+#include 
+
+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;
+   if (count <= 0)
+   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 & 0x;


Why mask 'address' if 'state' is u32 ?


+   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;


The ACPI and the PSCI code are not self contained here.

It would be nice to move this function to the ACPI code.


+}
+#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);
+


acpi_disabled - acpi_disabled - acpi_disabled everywhere :/

The enable-method approach is not straightforward and now it is polluted 
by acpi-disabled.


So IIUC,

smp_init_cpus (contains acpi_disabled)
  smp_cpu_setup
cpu_read_ops
  cpu_read_enable_method (contains acpi_disabled)
acpi_get_enable_method (returns 'psci' after checking 
psci_is_present)


Then psci_cpu_init_idle is called... and check again acpi_disabled.

IMO, the circumlocution with the psci vs acpi vs acpi_disabled is 
getting unnecessary too complex, is prone to error and will lead to 
unmaintainable code very soon.


I suggest to sort out encapsulation and self-contained code before 
adding more feature in this area.




cpu_node = of_get_cpu_node(cpu, NULL);
if (!cpu_node)
return -ENODEV;
diff --git a/include/linux/cpuidle-arm.h b/include/linux/cpuidle-arm.h
new file mode 100644
index ..b99bcb3f43dd
--- /dev/null
+++ b/include/linux/cpuidle-arm.h


arm-cpuidle.h for consistency with other (ARM) include/linux files ?


@@ -0,0 +1,30 @@
+#include 
+
+#include 
+
+/*
+ * arm_enter_idle_state - Programs CPU to enter the specified state
+ */
+static int arm_generic_enter_idle_state(int idx)
+{
+   int ret;
+
+   if (!idx) {
+   cpu_do_idle();
+   return idx;
+   }
+
+   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);
+
+   cpu_pm_exit();
+   }
+
+   re

Re: [PATCH v6 4/5] arm64: add support for ACPI Low Power Idle(LPI)

2016-06-27 Thread Sudeep Holla

Hi, Daniel,

On 24/06/16 22:04, Daniel Lezcano wrote:

[...]


+
+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 & 0x;


Why is needed to mask 'address' ?



This is as per Section 3.1.1 FFH Usage in LPI state entry methods in [1]

[...]


  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);


Is it possible the case where there is information in both the DT and in
ACPI ? So ACPI is enabled without idle information which is in the DT ?



No, as Rafael mentioned aready.



Either you do this, or we have to add it somehow somewhere in
drivers/cpuidle to avoid duplicating it.

@Daniel: do you have an opinion on this please ?


Yes, this function should be added to avoid duplication.



So, I assume you are happy with the way it's handled in this patch ?
(I will rename the file as suggested by Lorenzo)

--
Regards,
Sudeep

[1] 
http://infocenter.arm.com/help/topic/com.arm.doc.den0048a/DEN0048A_ARM_FFH_Specification.pdf


Re: [PATCH v6 4/5] arm64: add support for ACPI Low Power Idle(LPI)

2016-06-25 Thread Daniel Lezcano

On 06/25/2016 12:47 AM, Rafael J. Wysocki wrote:

[ ... ]


+   if (!acpi_disabled)
+   return psci_acpi_cpu_init_idle(cpu);


Is it possible the case where there is information in both the DT and in
ACPI ?


No, it isn't.

It is either-or, never both at the same time.


Ok, thanks for the clarification.

  -- Daniel


--
  Linaro.org │ Open source software for ARM SoCs

Follow Linaro:   Facebook |
 Twitter |
 Blog



Re: [PATCH v6 4/5] arm64: add support for ACPI Low Power Idle(LPI)

2016-06-24 Thread Rafael J. Wysocki
On Friday, June 24, 2016 11:04:07 PM Daniel Lezcano wrote:
> On 06/22/2016 04:17 PM, Lorenzo Pieralisi wrote:
> > Hi Sudeep,
> >
> > On Tue, Jun 14, 2016 at 03:48:38PM +0100, Sudeep Holla wrote:
> >> This patch adds appropriate callbacks to support ACPI Low Power Idle
> >> (LPI) on ARM64.
> >>
> >> Now that arm_enter_idle_state is exactly same in both generic ARM{32,64}
> >> CPUIdle driver and ARM64 backend for ACPI processor idle driver, we can
> >> unify it and move to cpuidle-arm.h header.
> >>
> >> Cc: Lorenzo Pieralisi 
> >> Cc: Mark Rutland 
> >> Cc: Daniel Lezcano 
> >> Cc: "Rafael J. Wysocki" 
> >> Cc: linux-arm-ker...@lists.infradead.org
> >> Signed-off-by: Sudeep Holla 
> >> ---
> >>   arch/arm64/kernel/cpuidle.c   | 17 +
> >>   drivers/cpuidle/cpuidle-arm.c | 23 ++
> >>   drivers/firmware/psci.c   | 56 
> >> +++
> >>   include/linux/cpuidle-arm.h   | 30 +++
> >>   4 files changed, 105 insertions(+), 21 deletions(-)
> >>   create mode 100644 include/linux/cpuidle-arm.h
> >
> > This patch seems fine by me, it would be good if Daniel can have
> > a look too.
> >
> > Some minor comments below.
> >
> > [...]
> >
> >> diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
> >> index 03e04582791c..c6caa863d156 100644
> >> --- a/drivers/firmware/psci.c
> >> +++ b/drivers/firmware/psci.c
> >> @@ -13,6 +13,7 @@
> >>
> >>   #define pr_fmt(fmt) "psci: " fmt
> >>
> >> +#include 
> >>   #include 
> >>   #include 
> >>   #include 
> >> @@ -310,11 +311,66 @@ static int psci_dt_cpu_init_idle(struct device_node 
> >> *cpu_node, int cpu)
> >>return ret;
> >>   }
> >>
> >> +#ifdef CONFIG_ACPI
> >> +#include 
> >> +
> >> +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;
> >> +  if (count <= 0)
> >> +  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 & 0x;
> 
> Why is needed to mask 'address' ?
> 
> >> +  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;
> >
> > Most of the code in this function is FW independent, it would be nice
> > to factor it out and add the respective ACPI/DT helper functions to
> > retrieve idle states count and parameters, we can update it later
> > anyway it is fine by me to leave it as it is.
> >
> >> +}
> >> +#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);
> 
> Is it possible the case where there is information in both the DT and in 
> ACPI ?

No, it isn't.

It is either-or, never both at the same time.

Thanks,
Rafael



Re: [PATCH v6 4/5] arm64: add support for ACPI Low Power Idle(LPI)

2016-06-24 Thread Daniel Lezcano

On 06/22/2016 04:17 PM, Lorenzo Pieralisi wrote:

Hi Sudeep,

On Tue, Jun 14, 2016 at 03:48:38PM +0100, Sudeep Holla wrote:

This patch adds appropriate callbacks to support ACPI Low Power Idle
(LPI) on ARM64.

Now that arm_enter_idle_state is exactly same in both generic ARM{32,64}
CPUIdle driver and ARM64 backend for ACPI processor idle driver, we can
unify it and move to cpuidle-arm.h header.

Cc: Lorenzo Pieralisi 
Cc: Mark Rutland 
Cc: Daniel Lezcano 
Cc: "Rafael J. Wysocki" 
Cc: linux-arm-ker...@lists.infradead.org
Signed-off-by: Sudeep Holla 
---
  arch/arm64/kernel/cpuidle.c   | 17 +
  drivers/cpuidle/cpuidle-arm.c | 23 ++
  drivers/firmware/psci.c   | 56 +++
  include/linux/cpuidle-arm.h   | 30 +++
  4 files changed, 105 insertions(+), 21 deletions(-)
  create mode 100644 include/linux/cpuidle-arm.h


This patch seems fine by me, it would be good if Daniel can have
a look too.

Some minor comments below.

[...]


diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
index 03e04582791c..c6caa863d156 100644
--- a/drivers/firmware/psci.c
+++ b/drivers/firmware/psci.c
@@ -13,6 +13,7 @@

  #define pr_fmt(fmt) "psci: " fmt

+#include 
  #include 
  #include 
  #include 
@@ -310,11 +311,66 @@ static int psci_dt_cpu_init_idle(struct device_node 
*cpu_node, int cpu)
return ret;
  }

+#ifdef CONFIG_ACPI
+#include 
+
+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;
+   if (count <= 0)
+   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 & 0x;


Why is needed to mask 'address' ?


+   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;


Most of the code in this function is FW independent, it would be nice
to factor it out and add the respective ACPI/DT helper functions to
retrieve idle states count and parameters, we can update it later
anyway it is fine by me to leave it as it is.


+}
+#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);


Is it possible the case where there is information in both the DT and in 
ACPI ? So ACPI is enabled without idle information which is in the DT ?



cpu_node = of_get_cpu_node(cpu, NULL);
if (!cpu_node)
return -ENODEV;
diff --git a/include/linux/cpuidle-arm.h b/include/linux/cpuidle-arm.h
new file mode 100644
index ..b99bcb3f43dd
--- /dev/null
+++ b/include/linux/cpuidle-arm.h


arm-cpuidle.h for consistency with other (ARM) include/linux files ?


@@ -0,0 +1,30 @@
+#include 
+
+#include 
+
+/*
+ * arm_enter_idle_state - Programs CPU to enter the specified state
+ */
+static int arm_generic_enter_idle_state(int idx)
+{
+   int ret;
+
+   if (!idx) {
+   cpu_do_idle();
+   return idx;
+   }
+
+   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);
+
+   cpu_pm_exit();
+   }
+
+   return ret ? -1 : idx;
+}


Either you do this, or we have to add it somehow somewhere in
drivers/cpuidle to avoid duplicating it.

@Daniel: do you have an opinion on this please ?


Yes, this function should be added to avoid duplication.

 -- Daniel


--
  Linaro.org │ Open source software for ARM SoCs

Follow Linaro:   Facebook |
 Twitter |

Re: [PATCH v6 4/5] arm64: add support for ACPI Low Power Idle(LPI)

2016-06-22 Thread Lorenzo Pieralisi
Hi Sudeep,

On Tue, Jun 14, 2016 at 03:48:38PM +0100, Sudeep Holla wrote:
> This patch adds appropriate callbacks to support ACPI Low Power Idle
> (LPI) on ARM64.
> 
> Now that arm_enter_idle_state is exactly same in both generic ARM{32,64}
> CPUIdle driver and ARM64 backend for ACPI processor idle driver, we can
> unify it and move to cpuidle-arm.h header.
> 
> Cc: Lorenzo Pieralisi 
> Cc: Mark Rutland 
> Cc: Daniel Lezcano 
> Cc: "Rafael J. Wysocki" 
> Cc: linux-arm-ker...@lists.infradead.org
> Signed-off-by: Sudeep Holla 
> ---
>  arch/arm64/kernel/cpuidle.c   | 17 +
>  drivers/cpuidle/cpuidle-arm.c | 23 ++
>  drivers/firmware/psci.c   | 56 
> +++
>  include/linux/cpuidle-arm.h   | 30 +++
>  4 files changed, 105 insertions(+), 21 deletions(-)
>  create mode 100644 include/linux/cpuidle-arm.h

This patch seems fine by me, it would be good if Daniel can have
a look too.

Some minor comments below.

[...]

> diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
> index 03e04582791c..c6caa863d156 100644
> --- a/drivers/firmware/psci.c
> +++ b/drivers/firmware/psci.c
> @@ -13,6 +13,7 @@
>  
>  #define pr_fmt(fmt) "psci: " fmt
>  
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -310,11 +311,66 @@ static int psci_dt_cpu_init_idle(struct device_node 
> *cpu_node, int cpu)
>   return ret;
>  }
>  
> +#ifdef CONFIG_ACPI
> +#include 
> +
> +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;
> + if (count <= 0)
> + 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 & 0x;
> + 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;

Most of the code in this function is FW independent, it would be nice
to factor it out and add the respective ACPI/DT helper functions to
retrieve idle states count and parameters, we can update it later
anyway it is fine by me to leave it as it is.

> +}
> +#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;
> diff --git a/include/linux/cpuidle-arm.h b/include/linux/cpuidle-arm.h
> new file mode 100644
> index ..b99bcb3f43dd
> --- /dev/null
> +++ b/include/linux/cpuidle-arm.h

arm-cpuidle.h for consistency with other (ARM) include/linux files ?

> @@ -0,0 +1,30 @@
> +#include 
> +
> +#include 
> +
> +/*
> + * arm_enter_idle_state - Programs CPU to enter the specified state
> + */
> +static int arm_generic_enter_idle_state(int idx)
> +{
> + int ret;
> +
> + if (!idx) {
> + cpu_do_idle();
> + return idx;
> + }
> +
> + 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);
> +
> + cpu_pm_exit();
> + }
> +
> + return ret ? -1 : idx;
> +}

Either you do this, or we have to add it somehow somewhere in
drivers/cpuidle to avoid duplicating it.

@Daniel: do you have an opinion on this please ?

Thanks,
Lorenzo


[PATCH v6 4/5] arm64: add support for ACPI Low Power Idle(LPI)

2016-06-14 Thread Sudeep Holla
This patch adds appropriate callbacks to support ACPI Low Power Idle
(LPI) on ARM64.

Now that arm_enter_idle_state is exactly same in both generic ARM{32,64}
CPUIdle driver and ARM64 backend for ACPI processor idle driver, we can
unify it and move to cpuidle-arm.h header.

Cc: Lorenzo Pieralisi 
Cc: Mark Rutland 
Cc: Daniel Lezcano 
Cc: "Rafael J. Wysocki" 
Cc: linux-arm-ker...@lists.infradead.org
Signed-off-by: Sudeep Holla 
---
 arch/arm64/kernel/cpuidle.c   | 17 +
 drivers/cpuidle/cpuidle-arm.c | 23 ++
 drivers/firmware/psci.c   | 56 +++
 include/linux/cpuidle-arm.h   | 30 +++
 4 files changed, 105 insertions(+), 21 deletions(-)
 create mode 100644 include/linux/cpuidle-arm.h

diff --git a/arch/arm64/kernel/cpuidle.c b/arch/arm64/kernel/cpuidle.c
index 06786fdaadeb..6874d01531ae 100644
--- a/arch/arm64/kernel/cpuidle.c
+++ b/arch/arm64/kernel/cpuidle.c
@@ -9,6 +9,8 @@
  * published by the Free Software Foundation.
  */
 
+#include 
+#include 
 #include 
 #include 
 
@@ -39,3 +41,18 @@ int arm_cpuidle_suspend(int index)
 
return cpu_ops[cpu]->cpu_suspend(index);
 }
+
+#ifdef CONFIG_ACPI
+
+#include 
+
+int acpi_processor_ffh_lpi_probe(unsigned int cpu)
+{
+   return arm_cpuidle_init(cpu);
+}
+
+int acpi_processor_ffh_lpi_enter(struct acpi_lpi_state *lpi)
+{
+   return arm_generic_enter_idle_state(lpi->index);
+}
+#endif
diff --git a/drivers/cpuidle/cpuidle-arm.c b/drivers/cpuidle/cpuidle-arm.c
index e342565e8715..75178ba4a1b2 100644
--- a/drivers/cpuidle/cpuidle-arm.c
+++ b/drivers/cpuidle/cpuidle-arm.c
@@ -12,8 +12,8 @@
 #define pr_fmt(fmt) "CPUidle arm: " fmt
 
 #include 
+#include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -36,26 +36,7 @@
 static int arm_enter_idle_state(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int idx)
 {
-   int ret;
-
-   if (!idx) {
-   cpu_do_idle();
-   return idx;
-   }
-
-   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);
-
-   cpu_pm_exit();
-   }
-
-   return ret ? -1 : idx;
+   return arm_generic_enter_idle_state(idx);
 }
 
 static struct cpuidle_driver arm_idle_driver = {
diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
index 03e04582791c..c6caa863d156 100644
--- a/drivers/firmware/psci.c
+++ b/drivers/firmware/psci.c
@@ -13,6 +13,7 @@
 
 #define pr_fmt(fmt) "psci: " fmt
 
+#include 
 #include 
 #include 
 #include 
@@ -310,11 +311,66 @@ static int psci_dt_cpu_init_idle(struct device_node 
*cpu_node, int cpu)
return ret;
 }
 
+#ifdef CONFIG_ACPI
+#include 
+
+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;
+   if (count <= 0)
+   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 & 0x;
+   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;
diff --git a/include/linux/cpuidle-arm.h b/include/linux/cpuidle-arm.h
new file mode 100644
index ..b99bcb3f43dd
--- /dev/null
+++ b/include/linux/cpuidle-arm.h
@@ -0,0 +1,30 @@
+#include 
+
+#include 
+
+/*
+ * arm_enter_idle_state - Programs CPU to enter the spe