All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 00/14] cpuidle: psci: Support hierarchical CPU arrangement
@ 2019-12-11 15:43 ` Ulf Hansson
  0 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-11 15:43 UTC (permalink / raw)
  To: Sudeep Holla, Lorenzo Pieralisi, Rob Herring, linux-pm
  Cc: Rafael J . Wysocki, Daniel Lezcano, Mark Rutland, Lina Iyer,
	Vincent Guittot, Stephen Boyd, Andy Gross, Bjorn Andersson,
	Kevin Hilman, Ulf Hansson, linux-arm-kernel, linux-arm-msm

Changes in v4:
	- Mover the check for OSI support from psci_dt_attach_cpu() to the
	caller's side of it.
	- Add comment in the code about using the deepest idle state as the
	triggering point for the domain state selection.
	- Folded in a patch to enable support for CPU hotplug.

Changes in v3:
	- Take one step further to completely avoid executing any OSI specific
	code from the ->enter() callback, while operating in the default PSCI
	Platform Coordinated mode.
	- Update example for the PSCI DT bindings to make it compile with
	"make dt_binding_check"

Changes in v2:
	- Avoid to affect the non-OSI path with specific changes for OSI. This
	forced me to re-order the series and a caused more or less minor changes
	to most of the patches.
	- Updated the DT bindings for PSCI to clarify and to include the "psci"
	name of the PM domain to attach to.
	- Replaced patch1 with another patch from Sudeep, solving the same
	problem, but in a different way.

This series enables initial support for hierarchical CPU arrangement, managed
by PSCI and its corresponding cpuidle driver. It's based on using the generic
PM domain (genpd), which nowadays also supports devices belonging to CPUs.

The last DTS patch enables the hierarchical topology to be used for the Qcom
410c Dragonboard, which supports the PSCI OS-initiated mode.

More detailed background can be found from previous submissions [1].

The series is also available at:
git.linaro.org/people/ulf.hansson/linux-pm.git next

Kind regards
Ulf Hansson

[1]
https://lwn.net/Articles/788306/


Lina Iyer (1):
  cpuidle: dt: Support hierarchical CPU idle states

Sudeep Holla (1):
  cpuidle: psci: Align psci_power_state count with idle state count

Ulf Hansson (12):
  dt: psci: Update DT bindings to support hierarchical PSCI states
  firmware: psci: Export functions to manage the OSI mode
  of: base: Add of_get_cpu_state_node() to get idle states for a CPU
    node
  cpuidle: psci: Simplify OF parsing of CPU idle state nodes
  cpuidle: psci: Support hierarchical CPU idle states
  cpuidle: psci: Add a helper to attach a CPU to its PM domain
  cpuidle: psci: Attach CPU devices to their PM domains
  cpuidle: psci: Prepare to use OS initiated suspend mode via PM domains
  cpuidle: psci: Manage runtime PM in the idle path
  cpuidle: psci: Support CPU hotplug for the hierarchical model
  cpuidle: psci: Add support for PM domains by using genpd
  arm64: dts: Convert to the hierarchical CPU topology layout for
    MSM8916

 .../devicetree/bindings/arm/cpus.yaml         |  15 +
 .../devicetree/bindings/arm/psci.yaml         | 104 ++++++
 arch/arm64/boot/dts/qcom/msm8916.dtsi         |  57 +++-
 drivers/cpuidle/Makefile                      |   4 +-
 drivers/cpuidle/cpuidle-psci-domain.c         | 298 ++++++++++++++++++
 drivers/cpuidle/cpuidle-psci.c                | 161 ++++++++--
 drivers/cpuidle/cpuidle-psci.h                |  17 +
 drivers/cpuidle/dt_idle_states.c              |   5 +-
 drivers/firmware/psci/psci.c                  |  18 +-
 drivers/of/base.c                             |  36 +++
 include/linux/cpuhotplug.h                    |   1 +
 include/linux/of.h                            |   8 +
 include/linux/psci.h                          |   2 +
 13 files changed, 691 insertions(+), 35 deletions(-)
 create mode 100644 drivers/cpuidle/cpuidle-psci-domain.c
 create mode 100644 drivers/cpuidle/cpuidle-psci.h

-- 
2.17.1


^ permalink raw reply	[flat|nested] 76+ messages in thread

* [PATCH v4 00/14] cpuidle: psci: Support hierarchical CPU arrangement
@ 2019-12-11 15:43 ` Ulf Hansson
  0 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-11 15:43 UTC (permalink / raw)
  To: Sudeep Holla, Lorenzo Pieralisi, Rob Herring, linux-pm
  Cc: Mark Rutland, Ulf Hansson, Kevin Hilman, Stephen Boyd,
	linux-arm-msm, Daniel Lezcano, Rafael J . Wysocki, Lina Iyer,
	Bjorn Andersson, Andy Gross, linux-arm-kernel

Changes in v4:
	- Mover the check for OSI support from psci_dt_attach_cpu() to the
	caller's side of it.
	- Add comment in the code about using the deepest idle state as the
	triggering point for the domain state selection.
	- Folded in a patch to enable support for CPU hotplug.

Changes in v3:
	- Take one step further to completely avoid executing any OSI specific
	code from the ->enter() callback, while operating in the default PSCI
	Platform Coordinated mode.
	- Update example for the PSCI DT bindings to make it compile with
	"make dt_binding_check"

Changes in v2:
	- Avoid to affect the non-OSI path with specific changes for OSI. This
	forced me to re-order the series and a caused more or less minor changes
	to most of the patches.
	- Updated the DT bindings for PSCI to clarify and to include the "psci"
	name of the PM domain to attach to.
	- Replaced patch1 with another patch from Sudeep, solving the same
	problem, but in a different way.

This series enables initial support for hierarchical CPU arrangement, managed
by PSCI and its corresponding cpuidle driver. It's based on using the generic
PM domain (genpd), which nowadays also supports devices belonging to CPUs.

The last DTS patch enables the hierarchical topology to be used for the Qcom
410c Dragonboard, which supports the PSCI OS-initiated mode.

More detailed background can be found from previous submissions [1].

The series is also available at:
git.linaro.org/people/ulf.hansson/linux-pm.git next

Kind regards
Ulf Hansson

[1]
https://lwn.net/Articles/788306/


Lina Iyer (1):
  cpuidle: dt: Support hierarchical CPU idle states

Sudeep Holla (1):
  cpuidle: psci: Align psci_power_state count with idle state count

Ulf Hansson (12):
  dt: psci: Update DT bindings to support hierarchical PSCI states
  firmware: psci: Export functions to manage the OSI mode
  of: base: Add of_get_cpu_state_node() to get idle states for a CPU
    node
  cpuidle: psci: Simplify OF parsing of CPU idle state nodes
  cpuidle: psci: Support hierarchical CPU idle states
  cpuidle: psci: Add a helper to attach a CPU to its PM domain
  cpuidle: psci: Attach CPU devices to their PM domains
  cpuidle: psci: Prepare to use OS initiated suspend mode via PM domains
  cpuidle: psci: Manage runtime PM in the idle path
  cpuidle: psci: Support CPU hotplug for the hierarchical model
  cpuidle: psci: Add support for PM domains by using genpd
  arm64: dts: Convert to the hierarchical CPU topology layout for
    MSM8916

 .../devicetree/bindings/arm/cpus.yaml         |  15 +
 .../devicetree/bindings/arm/psci.yaml         | 104 ++++++
 arch/arm64/boot/dts/qcom/msm8916.dtsi         |  57 +++-
 drivers/cpuidle/Makefile                      |   4 +-
 drivers/cpuidle/cpuidle-psci-domain.c         | 298 ++++++++++++++++++
 drivers/cpuidle/cpuidle-psci.c                | 161 ++++++++--
 drivers/cpuidle/cpuidle-psci.h                |  17 +
 drivers/cpuidle/dt_idle_states.c              |   5 +-
 drivers/firmware/psci/psci.c                  |  18 +-
 drivers/of/base.c                             |  36 +++
 include/linux/cpuhotplug.h                    |   1 +
 include/linux/of.h                            |   8 +
 include/linux/psci.h                          |   2 +
 13 files changed, 691 insertions(+), 35 deletions(-)
 create mode 100644 drivers/cpuidle/cpuidle-psci-domain.c
 create mode 100644 drivers/cpuidle/cpuidle-psci.h

-- 
2.17.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [PATCH v4 01/14] cpuidle: psci: Align psci_power_state count with idle state count
  2019-12-11 15:43 ` Ulf Hansson
@ 2019-12-11 15:43   ` Ulf Hansson
  -1 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-11 15:43 UTC (permalink / raw)
  To: Sudeep Holla, Lorenzo Pieralisi, Rob Herring, linux-pm
  Cc: Rafael J . Wysocki, Daniel Lezcano, Mark Rutland, Lina Iyer,
	Vincent Guittot, Stephen Boyd, Andy Gross, Bjorn Andersson,
	Kevin Hilman, Ulf Hansson, linux-arm-kernel, linux-arm-msm

From: Sudeep Holla <sudeep.holla@arm.com>

Instead of allocating 'n-1' states in psci_power_state to manage 'n'
idle states which include "ARM WFI" state, it would be simpler to have
1:1 mapping between psci_power_state and cpuidle driver states.

ARM WFI state(i.e. idx == 0) is handled specially in the generic macro
CPU_PM_CPU_IDLE_ENTER_PARAM and hence state[-1] is not possible. However
for sake of code readability, it is better to have 1:1 mapping and not
use [idx - 1] to access psci_power_state corresponding to driver cpuidle
state for idx.

psci_power_state[0] is default initialised to 0 and is never accessed
while entering WFI state.

Reported-by: Ulf Hansson <ulf.hansson@linaro.org>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
---

Changes in v4:
	- None.

---
 drivers/cpuidle/cpuidle-psci.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c
index f3c1a2396f98..361985f52ddd 100644
--- a/drivers/cpuidle/cpuidle-psci.c
+++ b/drivers/cpuidle/cpuidle-psci.c
@@ -30,7 +30,7 @@ static int psci_enter_idle_state(struct cpuidle_device *dev,
 	u32 *state = __this_cpu_read(psci_power_state);
 
 	return CPU_PM_CPU_IDLE_ENTER_PARAM(psci_cpu_suspend_enter,
-					   idx, state[idx - 1]);
+					   idx, state[idx]);
 }
 
 static struct cpuidle_driver psci_idle_driver __initdata = {
@@ -89,12 +89,14 @@ static int __init psci_dt_cpu_init_idle(struct device_node *cpu_node, int cpu)
 	if (!count)
 		return -ENODEV;
 
+	count++; /* Add WFI state too */
 	psci_states = kcalloc(count, sizeof(*psci_states), GFP_KERNEL);
 	if (!psci_states)
 		return -ENOMEM;
 
-	for (i = 0; i < count; i++) {
-		state_node = of_parse_phandle(cpu_node, "cpu-idle-states", i);
+	for (i = 1; i < count; i++) {
+		state_node = of_parse_phandle(cpu_node, "cpu-idle-states",
+					      i - 1);
 		ret = psci_dt_parse_state_node(state_node, &psci_states[i]);
 		of_node_put(state_node);
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 01/14] cpuidle: psci: Align psci_power_state count with idle state count
@ 2019-12-11 15:43   ` Ulf Hansson
  0 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-11 15:43 UTC (permalink / raw)
  To: Sudeep Holla, Lorenzo Pieralisi, Rob Herring, linux-pm
  Cc: Mark Rutland, Ulf Hansson, Kevin Hilman, Stephen Boyd,
	linux-arm-msm, Daniel Lezcano, Rafael J . Wysocki, Lina Iyer,
	Bjorn Andersson, Andy Gross, linux-arm-kernel

From: Sudeep Holla <sudeep.holla@arm.com>

Instead of allocating 'n-1' states in psci_power_state to manage 'n'
idle states which include "ARM WFI" state, it would be simpler to have
1:1 mapping between psci_power_state and cpuidle driver states.

ARM WFI state(i.e. idx == 0) is handled specially in the generic macro
CPU_PM_CPU_IDLE_ENTER_PARAM and hence state[-1] is not possible. However
for sake of code readability, it is better to have 1:1 mapping and not
use [idx - 1] to access psci_power_state corresponding to driver cpuidle
state for idx.

psci_power_state[0] is default initialised to 0 and is never accessed
while entering WFI state.

Reported-by: Ulf Hansson <ulf.hansson@linaro.org>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
---

Changes in v4:
	- None.

---
 drivers/cpuidle/cpuidle-psci.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c
index f3c1a2396f98..361985f52ddd 100644
--- a/drivers/cpuidle/cpuidle-psci.c
+++ b/drivers/cpuidle/cpuidle-psci.c
@@ -30,7 +30,7 @@ static int psci_enter_idle_state(struct cpuidle_device *dev,
 	u32 *state = __this_cpu_read(psci_power_state);
 
 	return CPU_PM_CPU_IDLE_ENTER_PARAM(psci_cpu_suspend_enter,
-					   idx, state[idx - 1]);
+					   idx, state[idx]);
 }
 
 static struct cpuidle_driver psci_idle_driver __initdata = {
@@ -89,12 +89,14 @@ static int __init psci_dt_cpu_init_idle(struct device_node *cpu_node, int cpu)
 	if (!count)
 		return -ENODEV;
 
+	count++; /* Add WFI state too */
 	psci_states = kcalloc(count, sizeof(*psci_states), GFP_KERNEL);
 	if (!psci_states)
 		return -ENOMEM;
 
-	for (i = 0; i < count; i++) {
-		state_node = of_parse_phandle(cpu_node, "cpu-idle-states", i);
+	for (i = 1; i < count; i++) {
+		state_node = of_parse_phandle(cpu_node, "cpu-idle-states",
+					      i - 1);
 		ret = psci_dt_parse_state_node(state_node, &psci_states[i]);
 		of_node_put(state_node);
 
-- 
2.17.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 02/14] dt: psci: Update DT bindings to support hierarchical PSCI states
  2019-12-11 15:43 ` Ulf Hansson
@ 2019-12-11 15:43   ` Ulf Hansson
  -1 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-11 15:43 UTC (permalink / raw)
  To: Sudeep Holla, Lorenzo Pieralisi, Rob Herring, linux-pm
  Cc: Rafael J . Wysocki, Daniel Lezcano, Mark Rutland, Lina Iyer,
	Vincent Guittot, Stephen Boyd, Andy Gross, Bjorn Andersson,
	Kevin Hilman, Ulf Hansson, linux-arm-kernel, linux-arm-msm,
	Lina Iyer

Update PSCI DT bindings to allow to represent idle states for CPUs and the
CPU topology, by using a hierarchical layout. Primarily this is done by
re-using the existing DT bindings for PM domains [1] and for PM domain idle
states [2].

Let's also add an example into the document for the PSCI DT bindings, to
clearly show the new hierarchical based layout. The currently supported
flattened layout, is already described in the ARM idle states bindings [3],
so let's leave that as is.

[1] Documentation/devicetree/bindings/power/power_domain.txt
[2] Documentation/devicetree/bindings/power/domain-idle-state.txt
[3] Documentation/devicetree/bindings/arm/idle-states.txt

Co-developed-by: Lina Iyer <lina.iyer@linaro.org>
Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
Reviewed-by: Sudeep Holla <sudeep.holla@arm.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---

Changes in v4:
	- None.

---
 .../devicetree/bindings/arm/cpus.yaml         |  15 +++
 .../devicetree/bindings/arm/psci.yaml         | 104 ++++++++++++++++++
 2 files changed, 119 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/cpus.yaml b/Documentation/devicetree/bindings/arm/cpus.yaml
index c23c24ff7575..7a9c3ce2dbef 100644
--- a/Documentation/devicetree/bindings/arm/cpus.yaml
+++ b/Documentation/devicetree/bindings/arm/cpus.yaml
@@ -242,6 +242,21 @@ properties:
 
       where voltage is in V, frequency is in MHz.
 
+  power-domains:
+    $ref: '/schemas/types.yaml#/definitions/phandle-array'
+    description:
+      List of phandles and PM domain specifiers, as defined by bindings of the
+      PM domain provider (see also ../power_domain.txt).
+
+  power-domain-names:
+    $ref: '/schemas/types.yaml#/definitions/string-array'
+    description:
+      A list of power domain name strings sorted in the same order as the
+      power-domains property.
+
+      For PSCI based platforms, the name corresponding to the index of the PSCI
+      PM domain provider, must be "psci".
+
   qcom,saw:
     $ref: '/schemas/types.yaml#/definitions/phandle'
     description: |
diff --git a/Documentation/devicetree/bindings/arm/psci.yaml b/Documentation/devicetree/bindings/arm/psci.yaml
index 7abdf58b335e..8ef85420b2ab 100644
--- a/Documentation/devicetree/bindings/arm/psci.yaml
+++ b/Documentation/devicetree/bindings/arm/psci.yaml
@@ -102,6 +102,34 @@ properties:
       [1] Kernel documentation - ARM idle states bindings
         Documentation/devicetree/bindings/arm/idle-states.txt
 
+  "#power-domain-cells":
+    description:
+      The number of cells in a PM domain specifier as per binding in [3].
+      Must be 0 as to represent a single PM domain.
+
+      ARM systems can have multiple cores, sometimes in an hierarchical
+      arrangement. This often, but not always, maps directly to the processor
+      power topology of the system. Individual nodes in a topology have their
+      own specific power states and can be better represented hierarchically.
+
+      For these cases, the definitions of the idle states for the CPUs and the
+      CPU topology, must conform to the binding in [3]. The idle states
+      themselves must conform to the binding in [4] and must specify the
+      arm,psci-suspend-param property.
+
+      It should also be noted that, in PSCI firmware v1.0 the OS-Initiated
+      (OSI) CPU suspend mode is introduced. Using a hierarchical representation
+      helps to implement support for OSI mode and OS implementations may choose
+      to mandate it.
+
+      [3] Documentation/devicetree/bindings/power/power_domain.txt
+      [4] Documentation/devicetree/bindings/power/domain-idle-state.txt
+
+  power-domains:
+    $ref: '/schemas/types.yaml#/definitions/phandle-array'
+    description:
+      List of phandles and PM domain specifiers, as defined by bindings of the
+      PM domain provider.
 
 required:
   - compatible
@@ -160,4 +188,80 @@ examples:
       cpu_on = <0x95c10002>;
       cpu_off = <0x95c10001>;
     };
+
+  - |+
+
+    // Case 4: CPUs and CPU idle states described using the hierarchical model.
+
+    cpus {
+      #size-cells = <0>;
+      #address-cells = <1>;
+
+      CPU0: cpu@0 {
+        device_type = "cpu";
+        compatible = "arm,cortex-a53", "arm,armv8";
+        reg = <0x0>;
+        enable-method = "psci";
+        power-domains = <&CPU_PD0>;
+        power-domain-names = "psci";
+      };
+
+      CPU1: cpu@1 {
+        device_type = "cpu";
+        compatible = "arm,cortex-a57", "arm,armv8";
+        reg = <0x100>;
+        enable-method = "psci";
+        power-domains = <&CPU_PD1>;
+        power-domain-names = "psci";
+      };
+
+      idle-states {
+
+        CPU_PWRDN: cpu-power-down {
+          compatible = "arm,idle-state";
+          arm,psci-suspend-param = <0x0000001>;
+          entry-latency-us = <10>;
+          exit-latency-us = <10>;
+          min-residency-us = <100>;
+        };
+
+        CLUSTER_RET: cluster-retention {
+          compatible = "domain-idle-state";
+          arm,psci-suspend-param = <0x1000011>;
+          entry-latency-us = <500>;
+          exit-latency-us = <500>;
+          min-residency-us = <2000>;
+        };
+
+        CLUSTER_PWRDN: cluster-power-down {
+          compatible = "domain-idle-state";
+          arm,psci-suspend-param = <0x1000031>;
+          entry-latency-us = <2000>;
+          exit-latency-us = <2000>;
+          min-residency-us = <6000>;
+        };
+      };
+    };
+
+    psci {
+      compatible = "arm,psci-1.0";
+      method = "smc";
+
+      CPU_PD0: cpu-pd0 {
+        #power-domain-cells = <0>;
+        domain-idle-states = <&CPU_PWRDN>;
+        power-domains = <&CLUSTER_PD>;
+      };
+
+      CPU_PD1: cpu-pd1 {
+        #power-domain-cells = <0>;
+        domain-idle-states =  <&CPU_PWRDN>;
+        power-domains = <&CLUSTER_PD>;
+      };
+
+      CLUSTER_PD: cluster-pd {
+        #power-domain-cells = <0>;
+        domain-idle-states = <&CLUSTER_RET>, <&CLUSTER_PWRDN>;
+      };
+    };
 ...
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 02/14] dt: psci: Update DT bindings to support hierarchical PSCI states
@ 2019-12-11 15:43   ` Ulf Hansson
  0 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-11 15:43 UTC (permalink / raw)
  To: Sudeep Holla, Lorenzo Pieralisi, Rob Herring, linux-pm
  Cc: Mark Rutland, Ulf Hansson, Kevin Hilman, Stephen Boyd,
	linux-arm-msm, Daniel Lezcano, Rafael J . Wysocki, Lina Iyer,
	Bjorn Andersson, Andy Gross, Lina Iyer, linux-arm-kernel

Update PSCI DT bindings to allow to represent idle states for CPUs and the
CPU topology, by using a hierarchical layout. Primarily this is done by
re-using the existing DT bindings for PM domains [1] and for PM domain idle
states [2].

Let's also add an example into the document for the PSCI DT bindings, to
clearly show the new hierarchical based layout. The currently supported
flattened layout, is already described in the ARM idle states bindings [3],
so let's leave that as is.

[1] Documentation/devicetree/bindings/power/power_domain.txt
[2] Documentation/devicetree/bindings/power/domain-idle-state.txt
[3] Documentation/devicetree/bindings/arm/idle-states.txt

Co-developed-by: Lina Iyer <lina.iyer@linaro.org>
Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
Reviewed-by: Sudeep Holla <sudeep.holla@arm.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---

Changes in v4:
	- None.

---
 .../devicetree/bindings/arm/cpus.yaml         |  15 +++
 .../devicetree/bindings/arm/psci.yaml         | 104 ++++++++++++++++++
 2 files changed, 119 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/cpus.yaml b/Documentation/devicetree/bindings/arm/cpus.yaml
index c23c24ff7575..7a9c3ce2dbef 100644
--- a/Documentation/devicetree/bindings/arm/cpus.yaml
+++ b/Documentation/devicetree/bindings/arm/cpus.yaml
@@ -242,6 +242,21 @@ properties:
 
       where voltage is in V, frequency is in MHz.
 
+  power-domains:
+    $ref: '/schemas/types.yaml#/definitions/phandle-array'
+    description:
+      List of phandles and PM domain specifiers, as defined by bindings of the
+      PM domain provider (see also ../power_domain.txt).
+
+  power-domain-names:
+    $ref: '/schemas/types.yaml#/definitions/string-array'
+    description:
+      A list of power domain name strings sorted in the same order as the
+      power-domains property.
+
+      For PSCI based platforms, the name corresponding to the index of the PSCI
+      PM domain provider, must be "psci".
+
   qcom,saw:
     $ref: '/schemas/types.yaml#/definitions/phandle'
     description: |
diff --git a/Documentation/devicetree/bindings/arm/psci.yaml b/Documentation/devicetree/bindings/arm/psci.yaml
index 7abdf58b335e..8ef85420b2ab 100644
--- a/Documentation/devicetree/bindings/arm/psci.yaml
+++ b/Documentation/devicetree/bindings/arm/psci.yaml
@@ -102,6 +102,34 @@ properties:
       [1] Kernel documentation - ARM idle states bindings
         Documentation/devicetree/bindings/arm/idle-states.txt
 
+  "#power-domain-cells":
+    description:
+      The number of cells in a PM domain specifier as per binding in [3].
+      Must be 0 as to represent a single PM domain.
+
+      ARM systems can have multiple cores, sometimes in an hierarchical
+      arrangement. This often, but not always, maps directly to the processor
+      power topology of the system. Individual nodes in a topology have their
+      own specific power states and can be better represented hierarchically.
+
+      For these cases, the definitions of the idle states for the CPUs and the
+      CPU topology, must conform to the binding in [3]. The idle states
+      themselves must conform to the binding in [4] and must specify the
+      arm,psci-suspend-param property.
+
+      It should also be noted that, in PSCI firmware v1.0 the OS-Initiated
+      (OSI) CPU suspend mode is introduced. Using a hierarchical representation
+      helps to implement support for OSI mode and OS implementations may choose
+      to mandate it.
+
+      [3] Documentation/devicetree/bindings/power/power_domain.txt
+      [4] Documentation/devicetree/bindings/power/domain-idle-state.txt
+
+  power-domains:
+    $ref: '/schemas/types.yaml#/definitions/phandle-array'
+    description:
+      List of phandles and PM domain specifiers, as defined by bindings of the
+      PM domain provider.
 
 required:
   - compatible
@@ -160,4 +188,80 @@ examples:
       cpu_on = <0x95c10002>;
       cpu_off = <0x95c10001>;
     };
+
+  - |+
+
+    // Case 4: CPUs and CPU idle states described using the hierarchical model.
+
+    cpus {
+      #size-cells = <0>;
+      #address-cells = <1>;
+
+      CPU0: cpu@0 {
+        device_type = "cpu";
+        compatible = "arm,cortex-a53", "arm,armv8";
+        reg = <0x0>;
+        enable-method = "psci";
+        power-domains = <&CPU_PD0>;
+        power-domain-names = "psci";
+      };
+
+      CPU1: cpu@1 {
+        device_type = "cpu";
+        compatible = "arm,cortex-a57", "arm,armv8";
+        reg = <0x100>;
+        enable-method = "psci";
+        power-domains = <&CPU_PD1>;
+        power-domain-names = "psci";
+      };
+
+      idle-states {
+
+        CPU_PWRDN: cpu-power-down {
+          compatible = "arm,idle-state";
+          arm,psci-suspend-param = <0x0000001>;
+          entry-latency-us = <10>;
+          exit-latency-us = <10>;
+          min-residency-us = <100>;
+        };
+
+        CLUSTER_RET: cluster-retention {
+          compatible = "domain-idle-state";
+          arm,psci-suspend-param = <0x1000011>;
+          entry-latency-us = <500>;
+          exit-latency-us = <500>;
+          min-residency-us = <2000>;
+        };
+
+        CLUSTER_PWRDN: cluster-power-down {
+          compatible = "domain-idle-state";
+          arm,psci-suspend-param = <0x1000031>;
+          entry-latency-us = <2000>;
+          exit-latency-us = <2000>;
+          min-residency-us = <6000>;
+        };
+      };
+    };
+
+    psci {
+      compatible = "arm,psci-1.0";
+      method = "smc";
+
+      CPU_PD0: cpu-pd0 {
+        #power-domain-cells = <0>;
+        domain-idle-states = <&CPU_PWRDN>;
+        power-domains = <&CLUSTER_PD>;
+      };
+
+      CPU_PD1: cpu-pd1 {
+        #power-domain-cells = <0>;
+        domain-idle-states =  <&CPU_PWRDN>;
+        power-domains = <&CLUSTER_PD>;
+      };
+
+      CLUSTER_PD: cluster-pd {
+        #power-domain-cells = <0>;
+        domain-idle-states = <&CLUSTER_RET>, <&CLUSTER_PWRDN>;
+      };
+    };
 ...
-- 
2.17.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 03/14] firmware: psci: Export functions to manage the OSI mode
  2019-12-11 15:43 ` Ulf Hansson
@ 2019-12-11 15:43   ` Ulf Hansson
  -1 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-11 15:43 UTC (permalink / raw)
  To: Sudeep Holla, Lorenzo Pieralisi, Rob Herring, linux-pm
  Cc: Rafael J . Wysocki, Daniel Lezcano, Mark Rutland, Lina Iyer,
	Vincent Guittot, Stephen Boyd, Andy Gross, Bjorn Andersson,
	Kevin Hilman, Ulf Hansson, linux-arm-kernel, linux-arm-msm

To allow subsequent changes to implement support for OSI mode through the
cpuidle-psci driver, export the existing psci_has_osi_support(). Export
also a new function, psci_set_osi_mode(), that allows its caller to enable
the OS-initiated CPU-suspend mode in the PSCI FW.

To deal with backwards compatibility for a kernel started through a kexec
call, default to set the CPU-suspend mode to the Platform Coordinated mode
during boot.

Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Reviewed-by: Sudeep Holla <sudeep.holla@arm.com>
---

Changes in v4:
	- None.

---
 drivers/firmware/psci/psci.c | 18 ++++++++++++++++--
 include/linux/psci.h         |  2 ++
 2 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/drivers/firmware/psci/psci.c b/drivers/firmware/psci/psci.c
index b3b6c15e7b36..2937d44b5df4 100644
--- a/drivers/firmware/psci/psci.c
+++ b/drivers/firmware/psci/psci.c
@@ -97,7 +97,7 @@ static inline bool psci_has_ext_power_state(void)
 				PSCI_1_0_FEATURES_CPU_SUSPEND_PF_MASK;
 }
 
-static inline bool psci_has_osi_support(void)
+bool psci_has_osi_support(void)
 {
 	return psci_cpu_suspend_feature & PSCI_1_0_OS_INITIATED;
 }
@@ -162,6 +162,15 @@ static u32 psci_get_version(void)
 	return invoke_psci_fn(PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0);
 }
 
+int psci_set_osi_mode(void)
+{
+	int err;
+
+	err = invoke_psci_fn(PSCI_1_0_FN_SET_SUSPEND_MODE,
+			     PSCI_1_0_SUSPEND_MODE_OSI, 0, 0);
+	return psci_to_linux_errno(err);
+}
+
 static int psci_cpu_suspend(u32 state, unsigned long entry_point)
 {
 	int err;
@@ -544,9 +553,14 @@ static int __init psci_1_0_init(struct device_node *np)
 	if (err)
 		return err;
 
-	if (psci_has_osi_support())
+	if (psci_has_osi_support()) {
 		pr_info("OSI mode supported.\n");
 
+		/* Default to PC mode. */
+		invoke_psci_fn(PSCI_1_0_FN_SET_SUSPEND_MODE,
+			       PSCI_1_0_SUSPEND_MODE_PC, 0, 0);
+	}
+
 	return 0;
 }
 
diff --git a/include/linux/psci.h b/include/linux/psci.h
index ebe0a881d13d..a67712b73b6c 100644
--- a/include/linux/psci.h
+++ b/include/linux/psci.h
@@ -18,6 +18,8 @@ bool psci_tos_resident_on(int cpu);
 
 int psci_cpu_suspend_enter(u32 state);
 bool psci_power_state_is_valid(u32 state);
+int psci_set_osi_mode(void);
+bool psci_has_osi_support(void);
 
 enum smccc_version {
 	SMCCC_VERSION_1_0,
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 03/14] firmware: psci: Export functions to manage the OSI mode
@ 2019-12-11 15:43   ` Ulf Hansson
  0 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-11 15:43 UTC (permalink / raw)
  To: Sudeep Holla, Lorenzo Pieralisi, Rob Herring, linux-pm
  Cc: Mark Rutland, Ulf Hansson, Kevin Hilman, Stephen Boyd,
	linux-arm-msm, Daniel Lezcano, Rafael J . Wysocki, Lina Iyer,
	Bjorn Andersson, Andy Gross, linux-arm-kernel

To allow subsequent changes to implement support for OSI mode through the
cpuidle-psci driver, export the existing psci_has_osi_support(). Export
also a new function, psci_set_osi_mode(), that allows its caller to enable
the OS-initiated CPU-suspend mode in the PSCI FW.

To deal with backwards compatibility for a kernel started through a kexec
call, default to set the CPU-suspend mode to the Platform Coordinated mode
during boot.

Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Reviewed-by: Sudeep Holla <sudeep.holla@arm.com>
---

Changes in v4:
	- None.

---
 drivers/firmware/psci/psci.c | 18 ++++++++++++++++--
 include/linux/psci.h         |  2 ++
 2 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/drivers/firmware/psci/psci.c b/drivers/firmware/psci/psci.c
index b3b6c15e7b36..2937d44b5df4 100644
--- a/drivers/firmware/psci/psci.c
+++ b/drivers/firmware/psci/psci.c
@@ -97,7 +97,7 @@ static inline bool psci_has_ext_power_state(void)
 				PSCI_1_0_FEATURES_CPU_SUSPEND_PF_MASK;
 }
 
-static inline bool psci_has_osi_support(void)
+bool psci_has_osi_support(void)
 {
 	return psci_cpu_suspend_feature & PSCI_1_0_OS_INITIATED;
 }
@@ -162,6 +162,15 @@ static u32 psci_get_version(void)
 	return invoke_psci_fn(PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0);
 }
 
+int psci_set_osi_mode(void)
+{
+	int err;
+
+	err = invoke_psci_fn(PSCI_1_0_FN_SET_SUSPEND_MODE,
+			     PSCI_1_0_SUSPEND_MODE_OSI, 0, 0);
+	return psci_to_linux_errno(err);
+}
+
 static int psci_cpu_suspend(u32 state, unsigned long entry_point)
 {
 	int err;
@@ -544,9 +553,14 @@ static int __init psci_1_0_init(struct device_node *np)
 	if (err)
 		return err;
 
-	if (psci_has_osi_support())
+	if (psci_has_osi_support()) {
 		pr_info("OSI mode supported.\n");
 
+		/* Default to PC mode. */
+		invoke_psci_fn(PSCI_1_0_FN_SET_SUSPEND_MODE,
+			       PSCI_1_0_SUSPEND_MODE_PC, 0, 0);
+	}
+
 	return 0;
 }
 
diff --git a/include/linux/psci.h b/include/linux/psci.h
index ebe0a881d13d..a67712b73b6c 100644
--- a/include/linux/psci.h
+++ b/include/linux/psci.h
@@ -18,6 +18,8 @@ bool psci_tos_resident_on(int cpu);
 
 int psci_cpu_suspend_enter(u32 state);
 bool psci_power_state_is_valid(u32 state);
+int psci_set_osi_mode(void);
+bool psci_has_osi_support(void);
 
 enum smccc_version {
 	SMCCC_VERSION_1_0,
-- 
2.17.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 04/14] of: base: Add of_get_cpu_state_node() to get idle states for a CPU node
  2019-12-11 15:43 ` Ulf Hansson
@ 2019-12-11 15:43   ` Ulf Hansson
  -1 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-11 15:43 UTC (permalink / raw)
  To: Sudeep Holla, Lorenzo Pieralisi, Rob Herring, linux-pm
  Cc: Rafael J . Wysocki, Daniel Lezcano, Mark Rutland, Lina Iyer,
	Vincent Guittot, Stephen Boyd, Andy Gross, Bjorn Andersson,
	Kevin Hilman, Ulf Hansson, linux-arm-kernel, linux-arm-msm,
	Lina Iyer

The CPU's idle state nodes are currently parsed at the common cpuidle DT
library, but also when initializing data for specific CPU idle operations,
as in the PSCI cpuidle driver case and qcom-spm cpuidle case.

To avoid open-coding, let's introduce of_get_cpu_state_node(), which takes
the device node for the CPU and the index to the requested idle state node,
as in-parameters. In case a corresponding idle state node is found, it
returns the node with the refcount incremented for it, else it returns
NULL.

Moreover, for PSCI there are two options to describe the CPU's idle states
[1], either via a flattened description or a hierarchical layout. Hence,
let's take both options into account.

[1] Documentation/devicetree/bindings/arm/psci.yaml

Suggested-by: Sudeep Holla <sudeep.holla@arm.com>
Co-developed-by: Lina Iyer <lina.iyer@linaro.org>
Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
Reviewed-by: Rob Herring <robh@kernel.org>
Reviewed-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Reviewed-by: Sudeep Holla <sudeep.holla@arm.com>
---

Changes in v4:
	- None.

---
 drivers/of/base.c  | 36 ++++++++++++++++++++++++++++++++++++
 include/linux/of.h |  8 ++++++++
 2 files changed, 44 insertions(+)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index db7fbc0c0893..614f0c674995 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -489,6 +489,42 @@ int of_cpu_node_to_id(struct device_node *cpu_node)
 }
 EXPORT_SYMBOL(of_cpu_node_to_id);
 
+/**
+ * of_get_cpu_state_node - Get CPU's idle state node at the given index
+ *
+ * @cpu_node: The device node for the CPU
+ * @index: The index in the list of the idle states
+ *
+ * Two generic methods can be used to describe a CPU's idle states, either via
+ * a flattened description through the "cpu-idle-states" binding or via the
+ * hierarchical layout, using the "power-domains" and the "domain-idle-states"
+ * bindings. This function check for both and returns the idle state node for
+ * the requested index.
+ *
+ * In case an idle state node is found at @index, the refcount is incremented
+ * for it, so call of_node_put() on it when done. Returns NULL if not found.
+ */
+struct device_node *of_get_cpu_state_node(struct device_node *cpu_node,
+					  int index)
+{
+	struct of_phandle_args args;
+	int err;
+
+	err = of_parse_phandle_with_args(cpu_node, "power-domains",
+					"#power-domain-cells", 0, &args);
+	if (!err) {
+		struct device_node *state_node =
+			of_parse_phandle(args.np, "domain-idle-states", index);
+
+		of_node_put(args.np);
+		if (state_node)
+			return state_node;
+	}
+
+	return of_parse_phandle(cpu_node, "cpu-idle-states", index);
+}
+EXPORT_SYMBOL(of_get_cpu_state_node);
+
 /**
  * __of_device_is_compatible() - Check if the node matches given constraints
  * @device: pointer to node
diff --git a/include/linux/of.h b/include/linux/of.h
index 844f89e1b039..c669c0a4732f 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -351,6 +351,8 @@ extern const void *of_get_property(const struct device_node *node,
 				int *lenp);
 extern struct device_node *of_get_cpu_node(int cpu, unsigned int *thread);
 extern struct device_node *of_get_next_cpu_node(struct device_node *prev);
+extern struct device_node *of_get_cpu_state_node(struct device_node *cpu_node,
+						 int index);
 
 #define for_each_property_of_node(dn, pp) \
 	for (pp = dn->properties; pp != NULL; pp = pp->next)
@@ -765,6 +767,12 @@ static inline struct device_node *of_get_next_cpu_node(struct device_node *prev)
 	return NULL;
 }
 
+static inline struct device_node *of_get_cpu_state_node(struct device_node *cpu_node,
+					int index)
+{
+	return NULL;
+}
+
 static inline int of_n_addr_cells(struct device_node *np)
 {
 	return 0;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 04/14] of: base: Add of_get_cpu_state_node() to get idle states for a CPU node
@ 2019-12-11 15:43   ` Ulf Hansson
  0 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-11 15:43 UTC (permalink / raw)
  To: Sudeep Holla, Lorenzo Pieralisi, Rob Herring, linux-pm
  Cc: Mark Rutland, Ulf Hansson, Kevin Hilman, Stephen Boyd,
	linux-arm-msm, Daniel Lezcano, Rafael J . Wysocki, Lina Iyer,
	Bjorn Andersson, Andy Gross, Lina Iyer, linux-arm-kernel

The CPU's idle state nodes are currently parsed at the common cpuidle DT
library, but also when initializing data for specific CPU idle operations,
as in the PSCI cpuidle driver case and qcom-spm cpuidle case.

To avoid open-coding, let's introduce of_get_cpu_state_node(), which takes
the device node for the CPU and the index to the requested idle state node,
as in-parameters. In case a corresponding idle state node is found, it
returns the node with the refcount incremented for it, else it returns
NULL.

Moreover, for PSCI there are two options to describe the CPU's idle states
[1], either via a flattened description or a hierarchical layout. Hence,
let's take both options into account.

[1] Documentation/devicetree/bindings/arm/psci.yaml

Suggested-by: Sudeep Holla <sudeep.holla@arm.com>
Co-developed-by: Lina Iyer <lina.iyer@linaro.org>
Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
Reviewed-by: Rob Herring <robh@kernel.org>
Reviewed-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Reviewed-by: Sudeep Holla <sudeep.holla@arm.com>
---

Changes in v4:
	- None.

---
 drivers/of/base.c  | 36 ++++++++++++++++++++++++++++++++++++
 include/linux/of.h |  8 ++++++++
 2 files changed, 44 insertions(+)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index db7fbc0c0893..614f0c674995 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -489,6 +489,42 @@ int of_cpu_node_to_id(struct device_node *cpu_node)
 }
 EXPORT_SYMBOL(of_cpu_node_to_id);
 
+/**
+ * of_get_cpu_state_node - Get CPU's idle state node at the given index
+ *
+ * @cpu_node: The device node for the CPU
+ * @index: The index in the list of the idle states
+ *
+ * Two generic methods can be used to describe a CPU's idle states, either via
+ * a flattened description through the "cpu-idle-states" binding or via the
+ * hierarchical layout, using the "power-domains" and the "domain-idle-states"
+ * bindings. This function check for both and returns the idle state node for
+ * the requested index.
+ *
+ * In case an idle state node is found at @index, the refcount is incremented
+ * for it, so call of_node_put() on it when done. Returns NULL if not found.
+ */
+struct device_node *of_get_cpu_state_node(struct device_node *cpu_node,
+					  int index)
+{
+	struct of_phandle_args args;
+	int err;
+
+	err = of_parse_phandle_with_args(cpu_node, "power-domains",
+					"#power-domain-cells", 0, &args);
+	if (!err) {
+		struct device_node *state_node =
+			of_parse_phandle(args.np, "domain-idle-states", index);
+
+		of_node_put(args.np);
+		if (state_node)
+			return state_node;
+	}
+
+	return of_parse_phandle(cpu_node, "cpu-idle-states", index);
+}
+EXPORT_SYMBOL(of_get_cpu_state_node);
+
 /**
  * __of_device_is_compatible() - Check if the node matches given constraints
  * @device: pointer to node
diff --git a/include/linux/of.h b/include/linux/of.h
index 844f89e1b039..c669c0a4732f 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -351,6 +351,8 @@ extern const void *of_get_property(const struct device_node *node,
 				int *lenp);
 extern struct device_node *of_get_cpu_node(int cpu, unsigned int *thread);
 extern struct device_node *of_get_next_cpu_node(struct device_node *prev);
+extern struct device_node *of_get_cpu_state_node(struct device_node *cpu_node,
+						 int index);
 
 #define for_each_property_of_node(dn, pp) \
 	for (pp = dn->properties; pp != NULL; pp = pp->next)
@@ -765,6 +767,12 @@ static inline struct device_node *of_get_next_cpu_node(struct device_node *prev)
 	return NULL;
 }
 
+static inline struct device_node *of_get_cpu_state_node(struct device_node *cpu_node,
+					int index)
+{
+	return NULL;
+}
+
 static inline int of_n_addr_cells(struct device_node *np)
 {
 	return 0;
-- 
2.17.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 05/14] cpuidle: dt: Support hierarchical CPU idle states
  2019-12-11 15:43 ` Ulf Hansson
@ 2019-12-11 15:43   ` Ulf Hansson
  -1 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-11 15:43 UTC (permalink / raw)
  To: Sudeep Holla, Lorenzo Pieralisi, Rob Herring, linux-pm
  Cc: Rafael J . Wysocki, Daniel Lezcano, Mark Rutland, Lina Iyer,
	Vincent Guittot, Stephen Boyd, Andy Gross, Bjorn Andersson,
	Kevin Hilman, Ulf Hansson, linux-arm-kernel, linux-arm-msm,
	Lina Iyer

From: Lina Iyer <lina.iyer@linaro.org>

Currently CPU's idle states are represented using the flattened model.
Let's add support for the hierarchical layout, via converting to use
of_get_cpu_state_node().

Suggested-by: Sudeep Holla <sudeep.holla@arm.com>
Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
Reviewed-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Co-developed-by: Ulf Hansson <ulf.hansson@linaro.org>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Reviewed-by: Sudeep Holla <sudeep.holla@arm.com>
---

Changes in v4:
	- None.

---
 drivers/cpuidle/dt_idle_states.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/cpuidle/dt_idle_states.c b/drivers/cpuidle/dt_idle_states.c
index d06d21a9525d..252f2a9686a6 100644
--- a/drivers/cpuidle/dt_idle_states.c
+++ b/drivers/cpuidle/dt_idle_states.c
@@ -111,8 +111,7 @@ static bool idle_state_valid(struct device_node *state_node, unsigned int idx,
 	for (cpu = cpumask_next(cpumask_first(cpumask), cpumask);
 	     cpu < nr_cpu_ids; cpu = cpumask_next(cpu, cpumask)) {
 		cpu_node = of_cpu_device_node_get(cpu);
-		curr_state_node = of_parse_phandle(cpu_node, "cpu-idle-states",
-						   idx);
+		curr_state_node = of_get_cpu_state_node(cpu_node, idx);
 		if (state_node != curr_state_node)
 			valid = false;
 
@@ -170,7 +169,7 @@ int dt_init_idle_driver(struct cpuidle_driver *drv,
 	cpu_node = of_cpu_device_node_get(cpumask_first(cpumask));
 
 	for (i = 0; ; i++) {
-		state_node = of_parse_phandle(cpu_node, "cpu-idle-states", i);
+		state_node = of_get_cpu_state_node(cpu_node, i);
 		if (!state_node)
 			break;
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 05/14] cpuidle: dt: Support hierarchical CPU idle states
@ 2019-12-11 15:43   ` Ulf Hansson
  0 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-11 15:43 UTC (permalink / raw)
  To: Sudeep Holla, Lorenzo Pieralisi, Rob Herring, linux-pm
  Cc: Mark Rutland, Ulf Hansson, Kevin Hilman, Stephen Boyd,
	linux-arm-msm, Daniel Lezcano, Rafael J . Wysocki, Lina Iyer,
	Bjorn Andersson, Andy Gross, Lina Iyer, linux-arm-kernel

From: Lina Iyer <lina.iyer@linaro.org>

Currently CPU's idle states are represented using the flattened model.
Let's add support for the hierarchical layout, via converting to use
of_get_cpu_state_node().

Suggested-by: Sudeep Holla <sudeep.holla@arm.com>
Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
Reviewed-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Co-developed-by: Ulf Hansson <ulf.hansson@linaro.org>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Reviewed-by: Sudeep Holla <sudeep.holla@arm.com>
---

Changes in v4:
	- None.

---
 drivers/cpuidle/dt_idle_states.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/cpuidle/dt_idle_states.c b/drivers/cpuidle/dt_idle_states.c
index d06d21a9525d..252f2a9686a6 100644
--- a/drivers/cpuidle/dt_idle_states.c
+++ b/drivers/cpuidle/dt_idle_states.c
@@ -111,8 +111,7 @@ static bool idle_state_valid(struct device_node *state_node, unsigned int idx,
 	for (cpu = cpumask_next(cpumask_first(cpumask), cpumask);
 	     cpu < nr_cpu_ids; cpu = cpumask_next(cpu, cpumask)) {
 		cpu_node = of_cpu_device_node_get(cpu);
-		curr_state_node = of_parse_phandle(cpu_node, "cpu-idle-states",
-						   idx);
+		curr_state_node = of_get_cpu_state_node(cpu_node, idx);
 		if (state_node != curr_state_node)
 			valid = false;
 
@@ -170,7 +169,7 @@ int dt_init_idle_driver(struct cpuidle_driver *drv,
 	cpu_node = of_cpu_device_node_get(cpumask_first(cpumask));
 
 	for (i = 0; ; i++) {
-		state_node = of_parse_phandle(cpu_node, "cpu-idle-states", i);
+		state_node = of_get_cpu_state_node(cpu_node, i);
 		if (!state_node)
 			break;
 
-- 
2.17.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 06/14] cpuidle: psci: Simplify OF parsing of CPU idle state nodes
  2019-12-11 15:43 ` Ulf Hansson
@ 2019-12-11 15:43   ` Ulf Hansson
  -1 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-11 15:43 UTC (permalink / raw)
  To: Sudeep Holla, Lorenzo Pieralisi, Rob Herring, linux-pm
  Cc: Rafael J . Wysocki, Daniel Lezcano, Mark Rutland, Lina Iyer,
	Vincent Guittot, Stephen Boyd, Andy Gross, Bjorn Andersson,
	Kevin Hilman, Ulf Hansson, linux-arm-kernel, linux-arm-msm

Iterating through the idle state nodes in DT, to find out the number of
states that needs to be allocated is unnecessary, as it has already been
done from dt_init_idle_driver(). Therefore, drop the iteration and use the
number we already have at hand.

Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Reviewed-by: Sudeep Holla <sudeep.holla@arm.com>
---

Changes in v4:
	- None.

---
 drivers/cpuidle/cpuidle-psci.c | 35 +++++++++++++++++-----------------
 1 file changed, 17 insertions(+), 18 deletions(-)

diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c
index 361985f52ddd..761359be50f2 100644
--- a/drivers/cpuidle/cpuidle-psci.c
+++ b/drivers/cpuidle/cpuidle-psci.c
@@ -73,30 +73,24 @@ static int __init psci_dt_parse_state_node(struct device_node *np, u32 *state)
 	return 0;
 }
 
-static int __init psci_dt_cpu_init_idle(struct device_node *cpu_node, int cpu)
+static int __init psci_dt_cpu_init_idle(struct device_node *cpu_node,
+					unsigned int state_count, int cpu)
 {
-	int i, ret = 0, count = 0;
+	int i, ret = 0;
 	u32 *psci_states;
 	struct device_node *state_node;
 
-	/* Count idle states */
-	while ((state_node = of_parse_phandle(cpu_node, "cpu-idle-states",
-					      count))) {
-		count++;
-		of_node_put(state_node);
-	}
-
-	if (!count)
-		return -ENODEV;
-
-	count++; /* Add WFI state too */
-	psci_states = kcalloc(count, sizeof(*psci_states), GFP_KERNEL);
+	state_count++; /* Add WFI state too */
+	psci_states = kcalloc(state_count, sizeof(*psci_states), GFP_KERNEL);
 	if (!psci_states)
 		return -ENOMEM;
 
-	for (i = 1; i < count; i++) {
+	for (i = 1; i < state_count; i++) {
 		state_node = of_parse_phandle(cpu_node, "cpu-idle-states",
 					      i - 1);
+		if (!state_node)
+			break;
+
 		ret = psci_dt_parse_state_node(state_node, &psci_states[i]);
 		of_node_put(state_node);
 
@@ -106,6 +100,11 @@ static int __init psci_dt_cpu_init_idle(struct device_node *cpu_node, int cpu)
 		pr_debug("psci-power-state %#x index %d\n", psci_states[i], i);
 	}
 
+	if (i != state_count) {
+		ret = -ENODEV;
+		goto free_mem;
+	}
+
 	/* Idle states parsed correctly, initialize per-cpu pointer */
 	per_cpu(psci_power_state, cpu) = psci_states;
 	return 0;
@@ -115,7 +114,7 @@ static int __init psci_dt_cpu_init_idle(struct device_node *cpu_node, int cpu)
 	return ret;
 }
 
-static __init int psci_cpu_init_idle(unsigned int cpu)
+static __init int psci_cpu_init_idle(unsigned int cpu, unsigned int state_count)
 {
 	struct device_node *cpu_node;
 	int ret;
@@ -131,7 +130,7 @@ static __init int psci_cpu_init_idle(unsigned int cpu)
 	if (!cpu_node)
 		return -ENODEV;
 
-	ret = psci_dt_cpu_init_idle(cpu_node, cpu);
+	ret = psci_dt_cpu_init_idle(cpu_node, state_count, cpu);
 
 	of_node_put(cpu_node);
 
@@ -187,7 +186,7 @@ static int __init psci_idle_init_cpu(int cpu)
 	/*
 	 * Initialize PSCI idle states.
 	 */
-	ret = psci_cpu_init_idle(cpu);
+	ret = psci_cpu_init_idle(cpu, ret);
 	if (ret) {
 		pr_err("CPU %d failed to PSCI idle\n", cpu);
 		goto out_kfree_drv;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 06/14] cpuidle: psci: Simplify OF parsing of CPU idle state nodes
@ 2019-12-11 15:43   ` Ulf Hansson
  0 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-11 15:43 UTC (permalink / raw)
  To: Sudeep Holla, Lorenzo Pieralisi, Rob Herring, linux-pm
  Cc: Mark Rutland, Ulf Hansson, Kevin Hilman, Stephen Boyd,
	linux-arm-msm, Daniel Lezcano, Rafael J . Wysocki, Lina Iyer,
	Bjorn Andersson, Andy Gross, linux-arm-kernel

Iterating through the idle state nodes in DT, to find out the number of
states that needs to be allocated is unnecessary, as it has already been
done from dt_init_idle_driver(). Therefore, drop the iteration and use the
number we already have at hand.

Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Reviewed-by: Sudeep Holla <sudeep.holla@arm.com>
---

Changes in v4:
	- None.

---
 drivers/cpuidle/cpuidle-psci.c | 35 +++++++++++++++++-----------------
 1 file changed, 17 insertions(+), 18 deletions(-)

diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c
index 361985f52ddd..761359be50f2 100644
--- a/drivers/cpuidle/cpuidle-psci.c
+++ b/drivers/cpuidle/cpuidle-psci.c
@@ -73,30 +73,24 @@ static int __init psci_dt_parse_state_node(struct device_node *np, u32 *state)
 	return 0;
 }
 
-static int __init psci_dt_cpu_init_idle(struct device_node *cpu_node, int cpu)
+static int __init psci_dt_cpu_init_idle(struct device_node *cpu_node,
+					unsigned int state_count, int cpu)
 {
-	int i, ret = 0, count = 0;
+	int i, ret = 0;
 	u32 *psci_states;
 	struct device_node *state_node;
 
-	/* Count idle states */
-	while ((state_node = of_parse_phandle(cpu_node, "cpu-idle-states",
-					      count))) {
-		count++;
-		of_node_put(state_node);
-	}
-
-	if (!count)
-		return -ENODEV;
-
-	count++; /* Add WFI state too */
-	psci_states = kcalloc(count, sizeof(*psci_states), GFP_KERNEL);
+	state_count++; /* Add WFI state too */
+	psci_states = kcalloc(state_count, sizeof(*psci_states), GFP_KERNEL);
 	if (!psci_states)
 		return -ENOMEM;
 
-	for (i = 1; i < count; i++) {
+	for (i = 1; i < state_count; i++) {
 		state_node = of_parse_phandle(cpu_node, "cpu-idle-states",
 					      i - 1);
+		if (!state_node)
+			break;
+
 		ret = psci_dt_parse_state_node(state_node, &psci_states[i]);
 		of_node_put(state_node);
 
@@ -106,6 +100,11 @@ static int __init psci_dt_cpu_init_idle(struct device_node *cpu_node, int cpu)
 		pr_debug("psci-power-state %#x index %d\n", psci_states[i], i);
 	}
 
+	if (i != state_count) {
+		ret = -ENODEV;
+		goto free_mem;
+	}
+
 	/* Idle states parsed correctly, initialize per-cpu pointer */
 	per_cpu(psci_power_state, cpu) = psci_states;
 	return 0;
@@ -115,7 +114,7 @@ static int __init psci_dt_cpu_init_idle(struct device_node *cpu_node, int cpu)
 	return ret;
 }
 
-static __init int psci_cpu_init_idle(unsigned int cpu)
+static __init int psci_cpu_init_idle(unsigned int cpu, unsigned int state_count)
 {
 	struct device_node *cpu_node;
 	int ret;
@@ -131,7 +130,7 @@ static __init int psci_cpu_init_idle(unsigned int cpu)
 	if (!cpu_node)
 		return -ENODEV;
 
-	ret = psci_dt_cpu_init_idle(cpu_node, cpu);
+	ret = psci_dt_cpu_init_idle(cpu_node, state_count, cpu);
 
 	of_node_put(cpu_node);
 
@@ -187,7 +186,7 @@ static int __init psci_idle_init_cpu(int cpu)
 	/*
 	 * Initialize PSCI idle states.
 	 */
-	ret = psci_cpu_init_idle(cpu);
+	ret = psci_cpu_init_idle(cpu, ret);
 	if (ret) {
 		pr_err("CPU %d failed to PSCI idle\n", cpu);
 		goto out_kfree_drv;
-- 
2.17.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 07/14] cpuidle: psci: Support hierarchical CPU idle states
  2019-12-11 15:43 ` Ulf Hansson
@ 2019-12-11 15:43   ` Ulf Hansson
  -1 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-11 15:43 UTC (permalink / raw)
  To: Sudeep Holla, Lorenzo Pieralisi, Rob Herring, linux-pm
  Cc: Rafael J . Wysocki, Daniel Lezcano, Mark Rutland, Lina Iyer,
	Vincent Guittot, Stephen Boyd, Andy Gross, Bjorn Andersson,
	Kevin Hilman, Ulf Hansson, linux-arm-kernel, linux-arm-msm

Currently CPU's idle states are represented using the flattened model.
Let's add support for the hierarchical layout, via converting to use
of_get_cpu_state_node().

Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Reviewed-by: Sudeep Holla <sudeep.holla@arm.com>
---

Changes in v4:
	- None.

---
 drivers/cpuidle/cpuidle-psci.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c
index 761359be50f2..830995b8a56f 100644
--- a/drivers/cpuidle/cpuidle-psci.c
+++ b/drivers/cpuidle/cpuidle-psci.c
@@ -86,8 +86,7 @@ static int __init psci_dt_cpu_init_idle(struct device_node *cpu_node,
 		return -ENOMEM;
 
 	for (i = 1; i < state_count; i++) {
-		state_node = of_parse_phandle(cpu_node, "cpu-idle-states",
-					      i - 1);
+		state_node = of_get_cpu_state_node(cpu_node, i - 1);
 		if (!state_node)
 			break;
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 07/14] cpuidle: psci: Support hierarchical CPU idle states
@ 2019-12-11 15:43   ` Ulf Hansson
  0 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-11 15:43 UTC (permalink / raw)
  To: Sudeep Holla, Lorenzo Pieralisi, Rob Herring, linux-pm
  Cc: Mark Rutland, Ulf Hansson, Kevin Hilman, Stephen Boyd,
	linux-arm-msm, Daniel Lezcano, Rafael J . Wysocki, Lina Iyer,
	Bjorn Andersson, Andy Gross, linux-arm-kernel

Currently CPU's idle states are represented using the flattened model.
Let's add support for the hierarchical layout, via converting to use
of_get_cpu_state_node().

Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Reviewed-by: Sudeep Holla <sudeep.holla@arm.com>
---

Changes in v4:
	- None.

---
 drivers/cpuidle/cpuidle-psci.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c
index 761359be50f2..830995b8a56f 100644
--- a/drivers/cpuidle/cpuidle-psci.c
+++ b/drivers/cpuidle/cpuidle-psci.c
@@ -86,8 +86,7 @@ static int __init psci_dt_cpu_init_idle(struct device_node *cpu_node,
 		return -ENOMEM;
 
 	for (i = 1; i < state_count; i++) {
-		state_node = of_parse_phandle(cpu_node, "cpu-idle-states",
-					      i - 1);
+		state_node = of_get_cpu_state_node(cpu_node, i - 1);
 		if (!state_node)
 			break;
 
-- 
2.17.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 08/14] cpuidle: psci: Add a helper to attach a CPU to its PM domain
  2019-12-11 15:43 ` Ulf Hansson
@ 2019-12-11 15:43   ` Ulf Hansson
  -1 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-11 15:43 UTC (permalink / raw)
  To: Sudeep Holla, Lorenzo Pieralisi, Rob Herring, linux-pm
  Cc: Rafael J . Wysocki, Daniel Lezcano, Mark Rutland, Lina Iyer,
	Vincent Guittot, Stephen Boyd, Andy Gross, Bjorn Andersson,
	Kevin Hilman, Ulf Hansson, linux-arm-kernel, linux-arm-msm

Introduce a PSCI DT helper function, psci_dt_attach_cpu(), which takes a
CPU number as an in-parameter and tries to attach the CPU's struct device
to its corresponding PM domain.

Let's makes use of dev_pm_domain_attach_by_name(), as it allows us to
specify "psci" as the "name" of the PM domain to attach to. Additionally,
let's also prepare the attached device to be power managed via runtime PM.

Note that, the implementation of the new helper function is in a new
separate c-file, which may seems a bit too much at this point. However,
subsequent changes that implements the remaining part of the PM domain
support for cpuidle-psci, helps to justify this split.

Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---

Changes in v4:
	- Drop check for OSI support in psci_dt_attach_cpu().

---
 drivers/cpuidle/Makefile              |  4 +++-
 drivers/cpuidle/cpuidle-psci-domain.c | 31 +++++++++++++++++++++++++++
 drivers/cpuidle/cpuidle-psci.h        | 12 +++++++++++
 3 files changed, 46 insertions(+), 1 deletion(-)
 create mode 100644 drivers/cpuidle/cpuidle-psci-domain.c
 create mode 100644 drivers/cpuidle/cpuidle-psci.h

diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile
index ee70d5cc5b99..cc8c769d7fa9 100644
--- a/drivers/cpuidle/Makefile
+++ b/drivers/cpuidle/Makefile
@@ -21,7 +21,9 @@ obj-$(CONFIG_ARM_U8500_CPUIDLE)         += cpuidle-ux500.o
 obj-$(CONFIG_ARM_AT91_CPUIDLE)          += cpuidle-at91.o
 obj-$(CONFIG_ARM_EXYNOS_CPUIDLE)        += cpuidle-exynos.o
 obj-$(CONFIG_ARM_CPUIDLE)		+= cpuidle-arm.o
-obj-$(CONFIG_ARM_PSCI_CPUIDLE)		+= cpuidle-psci.o
+obj-$(CONFIG_ARM_PSCI_CPUIDLE)		+= cpuidle_psci.o
+cpuidle_psci-y				:= cpuidle-psci.o
+cpuidle_psci-$(CONFIG_PM_GENERIC_DOMAINS_OF) += cpuidle-psci-domain.o
 
 ###############################################################################
 # MIPS drivers
diff --git a/drivers/cpuidle/cpuidle-psci-domain.c b/drivers/cpuidle/cpuidle-psci-domain.c
new file mode 100644
index 000000000000..656ef3d59149
--- /dev/null
+++ b/drivers/cpuidle/cpuidle-psci-domain.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PM domains for CPUs via genpd - managed by cpuidle-psci.
+ *
+ * Copyright (C) 2019 Linaro Ltd.
+ * Author: Ulf Hansson <ulf.hansson@linaro.org>
+ *
+ */
+
+#include <linux/cpu.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/pm_domain.h>
+#include <linux/pm_runtime.h>
+
+#include "cpuidle-psci.h"
+
+struct device *psci_dt_attach_cpu(int cpu)
+{
+	struct device *dev;
+
+	dev = dev_pm_domain_attach_by_name(get_cpu_device(cpu), "psci");
+	if (IS_ERR_OR_NULL(dev))
+		return dev;
+
+	pm_runtime_irq_safe(dev);
+	if (cpu_online(cpu))
+		pm_runtime_get_sync(dev);
+
+	return dev;
+}
diff --git a/drivers/cpuidle/cpuidle-psci.h b/drivers/cpuidle/cpuidle-psci.h
new file mode 100644
index 000000000000..0cadbb71dc55
--- /dev/null
+++ b/drivers/cpuidle/cpuidle-psci.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __CPUIDLE_PSCI_H
+#define __CPUIDLE_PSCI_H
+
+#ifdef CONFIG_PM_GENERIC_DOMAINS_OF
+struct device *psci_dt_attach_cpu(int cpu);
+#else
+static inline struct device *psci_dt_attach_cpu(int cpu) { return NULL; }
+#endif
+
+#endif /* __CPUIDLE_PSCI_H */
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 08/14] cpuidle: psci: Add a helper to attach a CPU to its PM domain
@ 2019-12-11 15:43   ` Ulf Hansson
  0 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-11 15:43 UTC (permalink / raw)
  To: Sudeep Holla, Lorenzo Pieralisi, Rob Herring, linux-pm
  Cc: Mark Rutland, Ulf Hansson, Kevin Hilman, Stephen Boyd,
	linux-arm-msm, Daniel Lezcano, Rafael J . Wysocki, Lina Iyer,
	Bjorn Andersson, Andy Gross, linux-arm-kernel

Introduce a PSCI DT helper function, psci_dt_attach_cpu(), which takes a
CPU number as an in-parameter and tries to attach the CPU's struct device
to its corresponding PM domain.

Let's makes use of dev_pm_domain_attach_by_name(), as it allows us to
specify "psci" as the "name" of the PM domain to attach to. Additionally,
let's also prepare the attached device to be power managed via runtime PM.

Note that, the implementation of the new helper function is in a new
separate c-file, which may seems a bit too much at this point. However,
subsequent changes that implements the remaining part of the PM domain
support for cpuidle-psci, helps to justify this split.

Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---

Changes in v4:
	- Drop check for OSI support in psci_dt_attach_cpu().

---
 drivers/cpuidle/Makefile              |  4 +++-
 drivers/cpuidle/cpuidle-psci-domain.c | 31 +++++++++++++++++++++++++++
 drivers/cpuidle/cpuidle-psci.h        | 12 +++++++++++
 3 files changed, 46 insertions(+), 1 deletion(-)
 create mode 100644 drivers/cpuidle/cpuidle-psci-domain.c
 create mode 100644 drivers/cpuidle/cpuidle-psci.h

diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile
index ee70d5cc5b99..cc8c769d7fa9 100644
--- a/drivers/cpuidle/Makefile
+++ b/drivers/cpuidle/Makefile
@@ -21,7 +21,9 @@ obj-$(CONFIG_ARM_U8500_CPUIDLE)         += cpuidle-ux500.o
 obj-$(CONFIG_ARM_AT91_CPUIDLE)          += cpuidle-at91.o
 obj-$(CONFIG_ARM_EXYNOS_CPUIDLE)        += cpuidle-exynos.o
 obj-$(CONFIG_ARM_CPUIDLE)		+= cpuidle-arm.o
-obj-$(CONFIG_ARM_PSCI_CPUIDLE)		+= cpuidle-psci.o
+obj-$(CONFIG_ARM_PSCI_CPUIDLE)		+= cpuidle_psci.o
+cpuidle_psci-y				:= cpuidle-psci.o
+cpuidle_psci-$(CONFIG_PM_GENERIC_DOMAINS_OF) += cpuidle-psci-domain.o
 
 ###############################################################################
 # MIPS drivers
diff --git a/drivers/cpuidle/cpuidle-psci-domain.c b/drivers/cpuidle/cpuidle-psci-domain.c
new file mode 100644
index 000000000000..656ef3d59149
--- /dev/null
+++ b/drivers/cpuidle/cpuidle-psci-domain.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PM domains for CPUs via genpd - managed by cpuidle-psci.
+ *
+ * Copyright (C) 2019 Linaro Ltd.
+ * Author: Ulf Hansson <ulf.hansson@linaro.org>
+ *
+ */
+
+#include <linux/cpu.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/pm_domain.h>
+#include <linux/pm_runtime.h>
+
+#include "cpuidle-psci.h"
+
+struct device *psci_dt_attach_cpu(int cpu)
+{
+	struct device *dev;
+
+	dev = dev_pm_domain_attach_by_name(get_cpu_device(cpu), "psci");
+	if (IS_ERR_OR_NULL(dev))
+		return dev;
+
+	pm_runtime_irq_safe(dev);
+	if (cpu_online(cpu))
+		pm_runtime_get_sync(dev);
+
+	return dev;
+}
diff --git a/drivers/cpuidle/cpuidle-psci.h b/drivers/cpuidle/cpuidle-psci.h
new file mode 100644
index 000000000000..0cadbb71dc55
--- /dev/null
+++ b/drivers/cpuidle/cpuidle-psci.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __CPUIDLE_PSCI_H
+#define __CPUIDLE_PSCI_H
+
+#ifdef CONFIG_PM_GENERIC_DOMAINS_OF
+struct device *psci_dt_attach_cpu(int cpu);
+#else
+static inline struct device *psci_dt_attach_cpu(int cpu) { return NULL; }
+#endif
+
+#endif /* __CPUIDLE_PSCI_H */
-- 
2.17.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 09/14] cpuidle: psci: Attach CPU devices to their PM domains
  2019-12-11 15:43 ` Ulf Hansson
@ 2019-12-11 15:43   ` Ulf Hansson
  -1 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-11 15:43 UTC (permalink / raw)
  To: Sudeep Holla, Lorenzo Pieralisi, Rob Herring, linux-pm
  Cc: Rafael J . Wysocki, Daniel Lezcano, Mark Rutland, Lina Iyer,
	Vincent Guittot, Stephen Boyd, Andy Gross, Bjorn Andersson,
	Kevin Hilman, Ulf Hansson, linux-arm-kernel, linux-arm-msm

In order to enable a CPU to be power managed through its PM domain, let's
try to attach it by calling psci_dt_attach_cpu() during the cpuidle
initialization.

psci_dt_attach_cpu() returns a pointer to the attached struct device, which
later should be used for runtime PM, hence we need to store it somewhere.
Rather than adding yet another per CPU variable, let's create a per CPU
struct to collect the relevant per CPU variables.

Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---

Changes in v4:
	- Add check for OSI support before calling psci_dt_attach_cpu().

---
 drivers/cpuidle/cpuidle-psci.c | 24 ++++++++++++++++++++----
 1 file changed, 20 insertions(+), 4 deletions(-)

diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c
index 830995b8a56f..6a87848be3c3 100644
--- a/drivers/cpuidle/cpuidle-psci.c
+++ b/drivers/cpuidle/cpuidle-psci.c
@@ -20,14 +20,20 @@
 
 #include <asm/cpuidle.h>
 
+#include "cpuidle-psci.h"
 #include "dt_idle_states.h"
 
-static DEFINE_PER_CPU_READ_MOSTLY(u32 *, psci_power_state);
+struct psci_cpuidle_data {
+	u32 *psci_states;
+	struct device *dev;
+};
+
+static DEFINE_PER_CPU_READ_MOSTLY(struct psci_cpuidle_data, psci_cpuidle_data);
 
 static int psci_enter_idle_state(struct cpuidle_device *dev,
 				struct cpuidle_driver *drv, int idx)
 {
-	u32 *state = __this_cpu_read(psci_power_state);
+	u32 *state = __this_cpu_read(psci_cpuidle_data.psci_states);
 
 	return CPU_PM_CPU_IDLE_ENTER_PARAM(psci_cpu_suspend_enter,
 					   idx, state[idx]);
@@ -79,6 +85,7 @@ static int __init psci_dt_cpu_init_idle(struct device_node *cpu_node,
 	int i, ret = 0;
 	u32 *psci_states;
 	struct device_node *state_node;
+	struct psci_cpuidle_data *data = per_cpu_ptr(&psci_cpuidle_data, cpu);
 
 	state_count++; /* Add WFI state too */
 	psci_states = kcalloc(state_count, sizeof(*psci_states), GFP_KERNEL);
@@ -104,8 +111,17 @@ static int __init psci_dt_cpu_init_idle(struct device_node *cpu_node,
 		goto free_mem;
 	}
 
-	/* Idle states parsed correctly, initialize per-cpu pointer */
-	per_cpu(psci_power_state, cpu) = psci_states;
+	/* Currently limit the hierarchical topology to be used in OSI mode. */
+	if (psci_has_osi_support()) {
+		data->dev = psci_dt_attach_cpu(cpu);
+		if (IS_ERR(data->dev)) {
+			ret = PTR_ERR(data->dev);
+			goto free_mem;
+		}
+	}
+
+	/* Idle states parsed correctly, store them in the per-cpu struct. */
+	data->psci_states = psci_states;
 	return 0;
 
 free_mem:
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 09/14] cpuidle: psci: Attach CPU devices to their PM domains
@ 2019-12-11 15:43   ` Ulf Hansson
  0 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-11 15:43 UTC (permalink / raw)
  To: Sudeep Holla, Lorenzo Pieralisi, Rob Herring, linux-pm
  Cc: Mark Rutland, Ulf Hansson, Kevin Hilman, Stephen Boyd,
	linux-arm-msm, Daniel Lezcano, Rafael J . Wysocki, Lina Iyer,
	Bjorn Andersson, Andy Gross, linux-arm-kernel

In order to enable a CPU to be power managed through its PM domain, let's
try to attach it by calling psci_dt_attach_cpu() during the cpuidle
initialization.

psci_dt_attach_cpu() returns a pointer to the attached struct device, which
later should be used for runtime PM, hence we need to store it somewhere.
Rather than adding yet another per CPU variable, let's create a per CPU
struct to collect the relevant per CPU variables.

Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---

Changes in v4:
	- Add check for OSI support before calling psci_dt_attach_cpu().

---
 drivers/cpuidle/cpuidle-psci.c | 24 ++++++++++++++++++++----
 1 file changed, 20 insertions(+), 4 deletions(-)

diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c
index 830995b8a56f..6a87848be3c3 100644
--- a/drivers/cpuidle/cpuidle-psci.c
+++ b/drivers/cpuidle/cpuidle-psci.c
@@ -20,14 +20,20 @@
 
 #include <asm/cpuidle.h>
 
+#include "cpuidle-psci.h"
 #include "dt_idle_states.h"
 
-static DEFINE_PER_CPU_READ_MOSTLY(u32 *, psci_power_state);
+struct psci_cpuidle_data {
+	u32 *psci_states;
+	struct device *dev;
+};
+
+static DEFINE_PER_CPU_READ_MOSTLY(struct psci_cpuidle_data, psci_cpuidle_data);
 
 static int psci_enter_idle_state(struct cpuidle_device *dev,
 				struct cpuidle_driver *drv, int idx)
 {
-	u32 *state = __this_cpu_read(psci_power_state);
+	u32 *state = __this_cpu_read(psci_cpuidle_data.psci_states);
 
 	return CPU_PM_CPU_IDLE_ENTER_PARAM(psci_cpu_suspend_enter,
 					   idx, state[idx]);
@@ -79,6 +85,7 @@ static int __init psci_dt_cpu_init_idle(struct device_node *cpu_node,
 	int i, ret = 0;
 	u32 *psci_states;
 	struct device_node *state_node;
+	struct psci_cpuidle_data *data = per_cpu_ptr(&psci_cpuidle_data, cpu);
 
 	state_count++; /* Add WFI state too */
 	psci_states = kcalloc(state_count, sizeof(*psci_states), GFP_KERNEL);
@@ -104,8 +111,17 @@ static int __init psci_dt_cpu_init_idle(struct device_node *cpu_node,
 		goto free_mem;
 	}
 
-	/* Idle states parsed correctly, initialize per-cpu pointer */
-	per_cpu(psci_power_state, cpu) = psci_states;
+	/* Currently limit the hierarchical topology to be used in OSI mode. */
+	if (psci_has_osi_support()) {
+		data->dev = psci_dt_attach_cpu(cpu);
+		if (IS_ERR(data->dev)) {
+			ret = PTR_ERR(data->dev);
+			goto free_mem;
+		}
+	}
+
+	/* Idle states parsed correctly, store them in the per-cpu struct. */
+	data->psci_states = psci_states;
 	return 0;
 
 free_mem:
-- 
2.17.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 10/14] cpuidle: psci: Prepare to use OS initiated suspend mode via PM domains
  2019-12-11 15:43 ` Ulf Hansson
@ 2019-12-11 15:43   ` Ulf Hansson
  -1 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-11 15:43 UTC (permalink / raw)
  To: Sudeep Holla, Lorenzo Pieralisi, Rob Herring, linux-pm
  Cc: Rafael J . Wysocki, Daniel Lezcano, Mark Rutland, Lina Iyer,
	Vincent Guittot, Stephen Boyd, Andy Gross, Bjorn Andersson,
	Kevin Hilman, Ulf Hansson, linux-arm-kernel, linux-arm-msm,
	Lina Iyer

The per CPU variable psci_power_state, contains an array of fixed values,
which reflects the corresponding arm,psci-suspend-param parsed from DT, for
each of the available CPU idle states.

This isn't sufficient when using the hierarchical CPU topology in DT, in
combination with having PSCI OS initiated (OSI) mode enabled. More
precisely, in OSI mode, Linux is responsible of telling the PSCI FW what
idle state the cluster (a group of CPUs) should enter, while in PSCI
Platform Coordinated (PC) mode, each CPU independently votes for an idle
state of the cluster.

For this reason, introduce a per CPU variable called domain_state and
implement two helper functions to read/write its value. Then let the
domain_state take precedence over the regular selected state, when entering
and idle state.

To avoid executing the above OSI specific code in the ->enter() callback,
while operating in the default PSCI Platform Coordinated mode, let's also
add a new enter-function and use it for OSI.

Co-developed-by: Lina Iyer <lina.iyer@linaro.org>
Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---

Changes in v4:
	- Rebased on top of earlier changes.
	- Add comment about using the deepest cpuidle state for the domain state
	selection.

---
 drivers/cpuidle/cpuidle-psci.c | 56 ++++++++++++++++++++++++++++++----
 1 file changed, 50 insertions(+), 6 deletions(-)

diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c
index 6a87848be3c3..9600fe674a89 100644
--- a/drivers/cpuidle/cpuidle-psci.c
+++ b/drivers/cpuidle/cpuidle-psci.c
@@ -29,14 +29,47 @@ struct psci_cpuidle_data {
 };
 
 static DEFINE_PER_CPU_READ_MOSTLY(struct psci_cpuidle_data, psci_cpuidle_data);
+static DEFINE_PER_CPU(u32, domain_state);
+
+static inline void psci_set_domain_state(u32 state)
+{
+	__this_cpu_write(domain_state, state);
+}
+
+static inline u32 psci_get_domain_state(void)
+{
+	return __this_cpu_read(domain_state);
+}
+
+static inline int psci_enter_state(int idx, u32 state)
+{
+	return CPU_PM_CPU_IDLE_ENTER_PARAM(psci_cpu_suspend_enter, idx, state);
+}
+
+static int psci_enter_domain_idle_state(struct cpuidle_device *dev,
+					struct cpuidle_driver *drv, int idx)
+{
+	struct psci_cpuidle_data *data = this_cpu_ptr(&psci_cpuidle_data);
+	u32 *states = data->psci_states;
+	u32 state = psci_get_domain_state();
+	int ret;
+
+	if (!state)
+		state = states[idx];
+
+	ret = psci_enter_state(idx, state);
+
+	/* Clear the domain state to start fresh when back from idle. */
+	psci_set_domain_state(0);
+	return ret;
+}
 
 static int psci_enter_idle_state(struct cpuidle_device *dev,
 				struct cpuidle_driver *drv, int idx)
 {
 	u32 *state = __this_cpu_read(psci_cpuidle_data.psci_states);
 
-	return CPU_PM_CPU_IDLE_ENTER_PARAM(psci_cpu_suspend_enter,
-					   idx, state[idx]);
+	return psci_enter_state(idx, state[idx]);
 }
 
 static struct cpuidle_driver psci_idle_driver __initdata = {
@@ -79,7 +112,8 @@ static int __init psci_dt_parse_state_node(struct device_node *np, u32 *state)
 	return 0;
 }
 
-static int __init psci_dt_cpu_init_idle(struct device_node *cpu_node,
+static int __init psci_dt_cpu_init_idle(struct cpuidle_driver *drv,
+					struct device_node *cpu_node,
 					unsigned int state_count, int cpu)
 {
 	int i, ret = 0;
@@ -118,6 +152,15 @@ static int __init psci_dt_cpu_init_idle(struct device_node *cpu_node,
 			ret = PTR_ERR(data->dev);
 			goto free_mem;
 		}
+
+		/*
+		 * Using the deepest state for the CPU to trigger a potential
+		 * selection of a shared state for the domain, assumes the
+		 * domain states are all deeper states.
+		 */
+		if (data->dev)
+			drv->states[state_count - 1].enter =
+				psci_enter_domain_idle_state;
 	}
 
 	/* Idle states parsed correctly, store them in the per-cpu struct. */
@@ -129,7 +172,8 @@ static int __init psci_dt_cpu_init_idle(struct device_node *cpu_node,
 	return ret;
 }
 
-static __init int psci_cpu_init_idle(unsigned int cpu, unsigned int state_count)
+static __init int psci_cpu_init_idle(struct cpuidle_driver *drv,
+				     unsigned int cpu, unsigned int state_count)
 {
 	struct device_node *cpu_node;
 	int ret;
@@ -145,7 +189,7 @@ static __init int psci_cpu_init_idle(unsigned int cpu, unsigned int state_count)
 	if (!cpu_node)
 		return -ENODEV;
 
-	ret = psci_dt_cpu_init_idle(cpu_node, state_count, cpu);
+	ret = psci_dt_cpu_init_idle(drv, cpu_node, state_count, cpu);
 
 	of_node_put(cpu_node);
 
@@ -201,7 +245,7 @@ static int __init psci_idle_init_cpu(int cpu)
 	/*
 	 * Initialize PSCI idle states.
 	 */
-	ret = psci_cpu_init_idle(cpu, ret);
+	ret = psci_cpu_init_idle(drv, cpu, ret);
 	if (ret) {
 		pr_err("CPU %d failed to PSCI idle\n", cpu);
 		goto out_kfree_drv;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 10/14] cpuidle: psci: Prepare to use OS initiated suspend mode via PM domains
@ 2019-12-11 15:43   ` Ulf Hansson
  0 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-11 15:43 UTC (permalink / raw)
  To: Sudeep Holla, Lorenzo Pieralisi, Rob Herring, linux-pm
  Cc: Mark Rutland, Ulf Hansson, Kevin Hilman, Stephen Boyd,
	linux-arm-msm, Daniel Lezcano, Rafael J . Wysocki, Lina Iyer,
	Bjorn Andersson, Andy Gross, Lina Iyer, linux-arm-kernel

The per CPU variable psci_power_state, contains an array of fixed values,
which reflects the corresponding arm,psci-suspend-param parsed from DT, for
each of the available CPU idle states.

This isn't sufficient when using the hierarchical CPU topology in DT, in
combination with having PSCI OS initiated (OSI) mode enabled. More
precisely, in OSI mode, Linux is responsible of telling the PSCI FW what
idle state the cluster (a group of CPUs) should enter, while in PSCI
Platform Coordinated (PC) mode, each CPU independently votes for an idle
state of the cluster.

For this reason, introduce a per CPU variable called domain_state and
implement two helper functions to read/write its value. Then let the
domain_state take precedence over the regular selected state, when entering
and idle state.

To avoid executing the above OSI specific code in the ->enter() callback,
while operating in the default PSCI Platform Coordinated mode, let's also
add a new enter-function and use it for OSI.

Co-developed-by: Lina Iyer <lina.iyer@linaro.org>
Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---

Changes in v4:
	- Rebased on top of earlier changes.
	- Add comment about using the deepest cpuidle state for the domain state
	selection.

---
 drivers/cpuidle/cpuidle-psci.c | 56 ++++++++++++++++++++++++++++++----
 1 file changed, 50 insertions(+), 6 deletions(-)

diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c
index 6a87848be3c3..9600fe674a89 100644
--- a/drivers/cpuidle/cpuidle-psci.c
+++ b/drivers/cpuidle/cpuidle-psci.c
@@ -29,14 +29,47 @@ struct psci_cpuidle_data {
 };
 
 static DEFINE_PER_CPU_READ_MOSTLY(struct psci_cpuidle_data, psci_cpuidle_data);
+static DEFINE_PER_CPU(u32, domain_state);
+
+static inline void psci_set_domain_state(u32 state)
+{
+	__this_cpu_write(domain_state, state);
+}
+
+static inline u32 psci_get_domain_state(void)
+{
+	return __this_cpu_read(domain_state);
+}
+
+static inline int psci_enter_state(int idx, u32 state)
+{
+	return CPU_PM_CPU_IDLE_ENTER_PARAM(psci_cpu_suspend_enter, idx, state);
+}
+
+static int psci_enter_domain_idle_state(struct cpuidle_device *dev,
+					struct cpuidle_driver *drv, int idx)
+{
+	struct psci_cpuidle_data *data = this_cpu_ptr(&psci_cpuidle_data);
+	u32 *states = data->psci_states;
+	u32 state = psci_get_domain_state();
+	int ret;
+
+	if (!state)
+		state = states[idx];
+
+	ret = psci_enter_state(idx, state);
+
+	/* Clear the domain state to start fresh when back from idle. */
+	psci_set_domain_state(0);
+	return ret;
+}
 
 static int psci_enter_idle_state(struct cpuidle_device *dev,
 				struct cpuidle_driver *drv, int idx)
 {
 	u32 *state = __this_cpu_read(psci_cpuidle_data.psci_states);
 
-	return CPU_PM_CPU_IDLE_ENTER_PARAM(psci_cpu_suspend_enter,
-					   idx, state[idx]);
+	return psci_enter_state(idx, state[idx]);
 }
 
 static struct cpuidle_driver psci_idle_driver __initdata = {
@@ -79,7 +112,8 @@ static int __init psci_dt_parse_state_node(struct device_node *np, u32 *state)
 	return 0;
 }
 
-static int __init psci_dt_cpu_init_idle(struct device_node *cpu_node,
+static int __init psci_dt_cpu_init_idle(struct cpuidle_driver *drv,
+					struct device_node *cpu_node,
 					unsigned int state_count, int cpu)
 {
 	int i, ret = 0;
@@ -118,6 +152,15 @@ static int __init psci_dt_cpu_init_idle(struct device_node *cpu_node,
 			ret = PTR_ERR(data->dev);
 			goto free_mem;
 		}
+
+		/*
+		 * Using the deepest state for the CPU to trigger a potential
+		 * selection of a shared state for the domain, assumes the
+		 * domain states are all deeper states.
+		 */
+		if (data->dev)
+			drv->states[state_count - 1].enter =
+				psci_enter_domain_idle_state;
 	}
 
 	/* Idle states parsed correctly, store them in the per-cpu struct. */
@@ -129,7 +172,8 @@ static int __init psci_dt_cpu_init_idle(struct device_node *cpu_node,
 	return ret;
 }
 
-static __init int psci_cpu_init_idle(unsigned int cpu, unsigned int state_count)
+static __init int psci_cpu_init_idle(struct cpuidle_driver *drv,
+				     unsigned int cpu, unsigned int state_count)
 {
 	struct device_node *cpu_node;
 	int ret;
@@ -145,7 +189,7 @@ static __init int psci_cpu_init_idle(unsigned int cpu, unsigned int state_count)
 	if (!cpu_node)
 		return -ENODEV;
 
-	ret = psci_dt_cpu_init_idle(cpu_node, state_count, cpu);
+	ret = psci_dt_cpu_init_idle(drv, cpu_node, state_count, cpu);
 
 	of_node_put(cpu_node);
 
@@ -201,7 +245,7 @@ static int __init psci_idle_init_cpu(int cpu)
 	/*
 	 * Initialize PSCI idle states.
 	 */
-	ret = psci_cpu_init_idle(cpu, ret);
+	ret = psci_cpu_init_idle(drv, cpu, ret);
 	if (ret) {
 		pr_err("CPU %d failed to PSCI idle\n", cpu);
 		goto out_kfree_drv;
-- 
2.17.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 11/14] cpuidle: psci: Manage runtime PM in the idle path
  2019-12-11 15:43 ` Ulf Hansson
@ 2019-12-11 15:43   ` Ulf Hansson
  -1 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-11 15:43 UTC (permalink / raw)
  To: Sudeep Holla, Lorenzo Pieralisi, Rob Herring, linux-pm
  Cc: Rafael J . Wysocki, Daniel Lezcano, Mark Rutland, Lina Iyer,
	Vincent Guittot, Stephen Boyd, Andy Gross, Bjorn Andersson,
	Kevin Hilman, Ulf Hansson, linux-arm-kernel, linux-arm-msm

In case we have succeeded to attach a CPU to its PM domain, let's deploy
runtime PM support for the corresponding attached device, to allow the CPU
to be powered-managed accordingly.

The triggering point for when runtime PM reference counting should be done,
has been selected to the deepest idle state for the CPU. However, from the
hierarchical point view, there may be good reasons to do runtime PM
reference counting even on shallower idle states, but at this point this
isn't supported, mainly due to limitations set by the generic PM domain.

Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---

Changes in v4:
	- None.

---
 drivers/cpuidle/cpuidle-psci.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c
index 9600fe674a89..6e7804e697ed 100644
--- a/drivers/cpuidle/cpuidle-psci.c
+++ b/drivers/cpuidle/cpuidle-psci.c
@@ -16,6 +16,7 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/psci.h>
+#include <linux/pm_runtime.h>
 #include <linux/slab.h>
 
 #include <asm/cpuidle.h>
@@ -51,14 +52,21 @@ static int psci_enter_domain_idle_state(struct cpuidle_device *dev,
 {
 	struct psci_cpuidle_data *data = this_cpu_ptr(&psci_cpuidle_data);
 	u32 *states = data->psci_states;
-	u32 state = psci_get_domain_state();
+	struct device *pd_dev = data->dev;
+	u32 state;
 	int ret;
 
+	/* Do runtime PM to manage a hierarchical CPU toplogy. */
+	pm_runtime_put_sync_suspend(pd_dev);
+
+	state = psci_get_domain_state();
 	if (!state)
 		state = states[idx];
 
 	ret = psci_enter_state(idx, state);
 
+	pm_runtime_get_sync(pd_dev);
+
 	/* Clear the domain state to start fresh when back from idle. */
 	psci_set_domain_state(0);
 	return ret;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 11/14] cpuidle: psci: Manage runtime PM in the idle path
@ 2019-12-11 15:43   ` Ulf Hansson
  0 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-11 15:43 UTC (permalink / raw)
  To: Sudeep Holla, Lorenzo Pieralisi, Rob Herring, linux-pm
  Cc: Mark Rutland, Ulf Hansson, Kevin Hilman, Stephen Boyd,
	linux-arm-msm, Daniel Lezcano, Rafael J . Wysocki, Lina Iyer,
	Bjorn Andersson, Andy Gross, linux-arm-kernel

In case we have succeeded to attach a CPU to its PM domain, let's deploy
runtime PM support for the corresponding attached device, to allow the CPU
to be powered-managed accordingly.

The triggering point for when runtime PM reference counting should be done,
has been selected to the deepest idle state for the CPU. However, from the
hierarchical point view, there may be good reasons to do runtime PM
reference counting even on shallower idle states, but at this point this
isn't supported, mainly due to limitations set by the generic PM domain.

Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---

Changes in v4:
	- None.

---
 drivers/cpuidle/cpuidle-psci.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c
index 9600fe674a89..6e7804e697ed 100644
--- a/drivers/cpuidle/cpuidle-psci.c
+++ b/drivers/cpuidle/cpuidle-psci.c
@@ -16,6 +16,7 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/psci.h>
+#include <linux/pm_runtime.h>
 #include <linux/slab.h>
 
 #include <asm/cpuidle.h>
@@ -51,14 +52,21 @@ static int psci_enter_domain_idle_state(struct cpuidle_device *dev,
 {
 	struct psci_cpuidle_data *data = this_cpu_ptr(&psci_cpuidle_data);
 	u32 *states = data->psci_states;
-	u32 state = psci_get_domain_state();
+	struct device *pd_dev = data->dev;
+	u32 state;
 	int ret;
 
+	/* Do runtime PM to manage a hierarchical CPU toplogy. */
+	pm_runtime_put_sync_suspend(pd_dev);
+
+	state = psci_get_domain_state();
 	if (!state)
 		state = states[idx];
 
 	ret = psci_enter_state(idx, state);
 
+	pm_runtime_get_sync(pd_dev);
+
 	/* Clear the domain state to start fresh when back from idle. */
 	psci_set_domain_state(0);
 	return ret;
-- 
2.17.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 12/14] cpuidle: psci: Support CPU hotplug for the hierarchical model
  2019-12-11 15:43 ` Ulf Hansson
@ 2019-12-11 15:43   ` Ulf Hansson
  -1 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-11 15:43 UTC (permalink / raw)
  To: Sudeep Holla, Lorenzo Pieralisi, Rob Herring, linux-pm
  Cc: Rafael J . Wysocki, Daniel Lezcano, Mark Rutland, Lina Iyer,
	Vincent Guittot, Stephen Boyd, Andy Gross, Bjorn Andersson,
	Kevin Hilman, Ulf Hansson, linux-arm-kernel, linux-arm-msm

When the hierarchical CPU topology is used and when a CPU is put offline,
that CPU prevents its PM domain from being powered off, which is because
genpd observes the corresponding attached device as being active from a
runtime PM point of view. Furthermore, any potential master PM domains are
also prevented from being powered off.

To address this limitation, let's add add a new CPU hotplug state
(CPUHP_AP_CPU_PM_STARTING) and register up/down callbacks for it, which
allows us to deal with runtime PM accordingly.

Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---

Changes in v4:
	- Folded in the patch to be part of the series.
	- Rebased on top of earlier changes.

---
 drivers/cpuidle/cpuidle-psci.c | 45 +++++++++++++++++++++++++++++++++-
 include/linux/cpuhotplug.h     |  1 +
 2 files changed, 45 insertions(+), 1 deletion(-)

diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c
index 6e7804e697ed..34a89d99bb0f 100644
--- a/drivers/cpuidle/cpuidle-psci.c
+++ b/drivers/cpuidle/cpuidle-psci.c
@@ -8,6 +8,7 @@
 
 #define pr_fmt(fmt) "CPUidle PSCI: " fmt
 
+#include <linux/cpuhotplug.h>
 #include <linux/cpuidle.h>
 #include <linux/cpumask.h>
 #include <linux/cpu_pm.h>
@@ -31,6 +32,7 @@ struct psci_cpuidle_data {
 
 static DEFINE_PER_CPU_READ_MOSTLY(struct psci_cpuidle_data, psci_cpuidle_data);
 static DEFINE_PER_CPU(u32, domain_state);
+static bool psci_cpuidle_use_cpuhp;
 
 static inline void psci_set_domain_state(u32 state)
 {
@@ -72,6 +74,44 @@ static int psci_enter_domain_idle_state(struct cpuidle_device *dev,
 	return ret;
 }
 
+static int psci_idle_cpuhp_up(unsigned int cpu)
+{
+	struct device *pd_dev = __this_cpu_read(psci_cpuidle_data.dev);
+
+	if (pd_dev)
+		pm_runtime_get_sync(pd_dev);
+
+	return 0;
+}
+
+static int psci_idle_cpuhp_down(unsigned int cpu)
+{
+	struct device *pd_dev = __this_cpu_read(psci_cpuidle_data.dev);
+
+	if (pd_dev) {
+		pm_runtime_put_sync(pd_dev);
+		/* Clear domain state to start fresh at next online. */
+		psci_set_domain_state(0);
+	}
+
+	return 0;
+}
+
+static void psci_idle_init_cpuhp(void)
+{
+	int err;
+
+	if (!psci_cpuidle_use_cpuhp)
+		return;
+
+	err = cpuhp_setup_state_nocalls(CPUHP_AP_CPU_PM_STARTING,
+					"cpuidle/psci:online",
+					psci_idle_cpuhp_up,
+					psci_idle_cpuhp_down);
+	if (err)
+		pr_warn("Failed %d while setup cpuhp state\n", err);
+}
+
 static int psci_enter_idle_state(struct cpuidle_device *dev,
 				struct cpuidle_driver *drv, int idx)
 {
@@ -166,9 +206,11 @@ static int __init psci_dt_cpu_init_idle(struct cpuidle_driver *drv,
 		 * selection of a shared state for the domain, assumes the
 		 * domain states are all deeper states.
 		 */
-		if (data->dev)
+		if (data->dev) {
 			drv->states[state_count - 1].enter =
 				psci_enter_domain_idle_state;
+			psci_cpuidle_use_cpuhp = true;
+		}
 	}
 
 	/* Idle states parsed correctly, store them in the per-cpu struct. */
@@ -289,6 +331,7 @@ static int __init psci_idle_init(void)
 			goto out_fail;
 	}
 
+	psci_idle_init_cpuhp();
 	return 0;
 
 out_fail:
diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
index e51ee772b9f5..01f04ed6ad92 100644
--- a/include/linux/cpuhotplug.h
+++ b/include/linux/cpuhotplug.h
@@ -95,6 +95,7 @@ enum cpuhp_state {
 	CPUHP_AP_OFFLINE,
 	CPUHP_AP_SCHED_STARTING,
 	CPUHP_AP_RCUTREE_DYING,
+	CPUHP_AP_CPU_PM_STARTING,
 	CPUHP_AP_IRQ_GIC_STARTING,
 	CPUHP_AP_IRQ_HIP04_STARTING,
 	CPUHP_AP_IRQ_ARMADA_XP_STARTING,
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 12/14] cpuidle: psci: Support CPU hotplug for the hierarchical model
@ 2019-12-11 15:43   ` Ulf Hansson
  0 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-11 15:43 UTC (permalink / raw)
  To: Sudeep Holla, Lorenzo Pieralisi, Rob Herring, linux-pm
  Cc: Mark Rutland, Ulf Hansson, Kevin Hilman, Stephen Boyd,
	linux-arm-msm, Daniel Lezcano, Rafael J . Wysocki, Lina Iyer,
	Bjorn Andersson, Andy Gross, linux-arm-kernel

When the hierarchical CPU topology is used and when a CPU is put offline,
that CPU prevents its PM domain from being powered off, which is because
genpd observes the corresponding attached device as being active from a
runtime PM point of view. Furthermore, any potential master PM domains are
also prevented from being powered off.

To address this limitation, let's add add a new CPU hotplug state
(CPUHP_AP_CPU_PM_STARTING) and register up/down callbacks for it, which
allows us to deal with runtime PM accordingly.

Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---

Changes in v4:
	- Folded in the patch to be part of the series.
	- Rebased on top of earlier changes.

---
 drivers/cpuidle/cpuidle-psci.c | 45 +++++++++++++++++++++++++++++++++-
 include/linux/cpuhotplug.h     |  1 +
 2 files changed, 45 insertions(+), 1 deletion(-)

diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c
index 6e7804e697ed..34a89d99bb0f 100644
--- a/drivers/cpuidle/cpuidle-psci.c
+++ b/drivers/cpuidle/cpuidle-psci.c
@@ -8,6 +8,7 @@
 
 #define pr_fmt(fmt) "CPUidle PSCI: " fmt
 
+#include <linux/cpuhotplug.h>
 #include <linux/cpuidle.h>
 #include <linux/cpumask.h>
 #include <linux/cpu_pm.h>
@@ -31,6 +32,7 @@ struct psci_cpuidle_data {
 
 static DEFINE_PER_CPU_READ_MOSTLY(struct psci_cpuidle_data, psci_cpuidle_data);
 static DEFINE_PER_CPU(u32, domain_state);
+static bool psci_cpuidle_use_cpuhp;
 
 static inline void psci_set_domain_state(u32 state)
 {
@@ -72,6 +74,44 @@ static int psci_enter_domain_idle_state(struct cpuidle_device *dev,
 	return ret;
 }
 
+static int psci_idle_cpuhp_up(unsigned int cpu)
+{
+	struct device *pd_dev = __this_cpu_read(psci_cpuidle_data.dev);
+
+	if (pd_dev)
+		pm_runtime_get_sync(pd_dev);
+
+	return 0;
+}
+
+static int psci_idle_cpuhp_down(unsigned int cpu)
+{
+	struct device *pd_dev = __this_cpu_read(psci_cpuidle_data.dev);
+
+	if (pd_dev) {
+		pm_runtime_put_sync(pd_dev);
+		/* Clear domain state to start fresh at next online. */
+		psci_set_domain_state(0);
+	}
+
+	return 0;
+}
+
+static void psci_idle_init_cpuhp(void)
+{
+	int err;
+
+	if (!psci_cpuidle_use_cpuhp)
+		return;
+
+	err = cpuhp_setup_state_nocalls(CPUHP_AP_CPU_PM_STARTING,
+					"cpuidle/psci:online",
+					psci_idle_cpuhp_up,
+					psci_idle_cpuhp_down);
+	if (err)
+		pr_warn("Failed %d while setup cpuhp state\n", err);
+}
+
 static int psci_enter_idle_state(struct cpuidle_device *dev,
 				struct cpuidle_driver *drv, int idx)
 {
@@ -166,9 +206,11 @@ static int __init psci_dt_cpu_init_idle(struct cpuidle_driver *drv,
 		 * selection of a shared state for the domain, assumes the
 		 * domain states are all deeper states.
 		 */
-		if (data->dev)
+		if (data->dev) {
 			drv->states[state_count - 1].enter =
 				psci_enter_domain_idle_state;
+			psci_cpuidle_use_cpuhp = true;
+		}
 	}
 
 	/* Idle states parsed correctly, store them in the per-cpu struct. */
@@ -289,6 +331,7 @@ static int __init psci_idle_init(void)
 			goto out_fail;
 	}
 
+	psci_idle_init_cpuhp();
 	return 0;
 
 out_fail:
diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
index e51ee772b9f5..01f04ed6ad92 100644
--- a/include/linux/cpuhotplug.h
+++ b/include/linux/cpuhotplug.h
@@ -95,6 +95,7 @@ enum cpuhp_state {
 	CPUHP_AP_OFFLINE,
 	CPUHP_AP_SCHED_STARTING,
 	CPUHP_AP_RCUTREE_DYING,
+	CPUHP_AP_CPU_PM_STARTING,
 	CPUHP_AP_IRQ_GIC_STARTING,
 	CPUHP_AP_IRQ_HIP04_STARTING,
 	CPUHP_AP_IRQ_ARMADA_XP_STARTING,
-- 
2.17.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 13/14] cpuidle: psci: Add support for PM domains by using genpd
  2019-12-11 15:43 ` Ulf Hansson
@ 2019-12-11 15:43   ` Ulf Hansson
  -1 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-11 15:43 UTC (permalink / raw)
  To: Sudeep Holla, Lorenzo Pieralisi, Rob Herring, linux-pm
  Cc: Rafael J . Wysocki, Daniel Lezcano, Mark Rutland, Lina Iyer,
	Vincent Guittot, Stephen Boyd, Andy Gross, Bjorn Andersson,
	Kevin Hilman, Ulf Hansson, linux-arm-kernel, linux-arm-msm,
	Lina Iyer

When the hierarchical CPU topology layout is used in DT and the PSCI OSI
mode is supported by the PSCI FW, let's initialize a corresponding PM
domain topology by using genpd. This enables a CPU and a group of CPUs,
when attached to the topology, to be power-managed accordingly.

To trigger the attempt to initialize the genpd data structures let's use a
subsys_initcall, which should be early enough to allow CPUs, but also other
devices to be attached.

The initialization consists of parsing the PSCI OF node for the topology
and the "domain idle states" DT bindings. In case the idle states are
compatible with "domain-idle-state", the initialized genpd becomes
responsible of selecting an idle state for the PM domain, via assigning it
a genpd governor.

Note that, a successful initialization of the genpd data structures, is
followed by a call to psci_set_osi_mode(), as to try to enable the OSI mode
in the PSCI FW. In case this fails, we fall back into a degraded mode
rather than bailing out and returning an error code.

Co-developed-by: Lina Iyer <lina.iyer@linaro.org>
Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---

Changes in v4:
	- None.

---
 drivers/cpuidle/cpuidle-psci-domain.c | 267 ++++++++++++++++++++++++++
 drivers/cpuidle/cpuidle-psci.c        |   4 +-
 drivers/cpuidle/cpuidle-psci.h        |   5 +
 3 files changed, 274 insertions(+), 2 deletions(-)

diff --git a/drivers/cpuidle/cpuidle-psci-domain.c b/drivers/cpuidle/cpuidle-psci-domain.c
index 656ef3d59149..c2f94ba42222 100644
--- a/drivers/cpuidle/cpuidle-psci-domain.c
+++ b/drivers/cpuidle/cpuidle-psci-domain.c
@@ -7,14 +7,281 @@
  *
  */
 
+#define pr_fmt(fmt) "CPUidle PSCI: " fmt
+
 #include <linux/cpu.h>
 #include <linux/device.h>
 #include <linux/kernel.h>
 #include <linux/pm_domain.h>
 #include <linux/pm_runtime.h>
+#include <linux/psci.h>
+#include <linux/slab.h>
+#include <linux/string.h>
 
 #include "cpuidle-psci.h"
 
+struct psci_pd_provider {
+	struct list_head link;
+	struct device_node *node;
+};
+
+static LIST_HEAD(psci_pd_providers);
+static bool osi_mode_enabled;
+
+static int psci_pd_power_off(struct generic_pm_domain *pd)
+{
+	struct genpd_power_state *state = &pd->states[pd->state_idx];
+	u32 *pd_state;
+
+	/* If we have failed to enable OSI mode, then abort power off. */
+	if (!osi_mode_enabled)
+		return -EBUSY;
+
+	if (!state->data)
+		return 0;
+
+	/* OSI mode is enabled, set the corresponding domain state. */
+	pd_state = state->data;
+	psci_set_domain_state(*pd_state);
+
+	return 0;
+}
+
+static int __init psci_pd_parse_state_nodes(struct genpd_power_state *states,
+					int state_count)
+{
+	int i, ret;
+	u32 psci_state, *psci_state_buf;
+
+	for (i = 0; i < state_count; i++) {
+		ret = psci_dt_parse_state_node(to_of_node(states[i].fwnode),
+					&psci_state);
+		if (ret)
+			goto free_state;
+
+		psci_state_buf = kmalloc(sizeof(u32), GFP_KERNEL);
+		if (!psci_state_buf) {
+			ret = -ENOMEM;
+			goto free_state;
+		}
+		*psci_state_buf = psci_state;
+		states[i].data = psci_state_buf;
+	}
+
+	return 0;
+
+free_state:
+	i--;
+	for (; i >= 0; i--)
+		kfree(states[i].data);
+	return ret;
+}
+
+static int __init psci_pd_parse_states(struct device_node *np,
+			struct genpd_power_state **states, int *state_count)
+{
+	int ret;
+
+	/* Parse the domain idle states. */
+	ret = of_genpd_parse_idle_states(np, states, state_count);
+	if (ret)
+		return ret;
+
+	/* Fill out the PSCI specifics for each found state. */
+	ret = psci_pd_parse_state_nodes(*states, *state_count);
+	if (ret)
+		kfree(*states);
+
+	return ret;
+}
+
+static void psci_pd_free_states(struct genpd_power_state *states,
+				unsigned int state_count)
+{
+	int i;
+
+	for (i = 0; i < state_count; i++)
+		kfree(states[i].data);
+	kfree(states);
+}
+
+static int __init psci_pd_init(struct device_node *np)
+{
+	struct generic_pm_domain *pd;
+	struct psci_pd_provider *pd_provider;
+	struct dev_power_governor *pd_gov;
+	struct genpd_power_state *states = NULL;
+	int ret = -ENOMEM, state_count = 0;
+
+	pd = kzalloc(sizeof(*pd), GFP_KERNEL);
+	if (!pd)
+		goto out;
+
+	pd_provider = kzalloc(sizeof(*pd_provider), GFP_KERNEL);
+	if (!pd_provider)
+		goto free_pd;
+
+	pd->name = kasprintf(GFP_KERNEL, "%pOF", np);
+	if (!pd->name)
+		goto free_pd_prov;
+
+	/*
+	 * Parse the domain idle states and let genpd manage the state selection
+	 * for those being compatible with "domain-idle-state".
+	 */
+	ret = psci_pd_parse_states(np, &states, &state_count);
+	if (ret)
+		goto free_name;
+
+	pd->free_states = psci_pd_free_states;
+	pd->name = kbasename(pd->name);
+	pd->power_off = psci_pd_power_off;
+	pd->states = states;
+	pd->state_count = state_count;
+	pd->flags |= GENPD_FLAG_IRQ_SAFE | GENPD_FLAG_CPU_DOMAIN;
+
+	/* Use governor for CPU PM domains if it has some states to manage. */
+	pd_gov = state_count > 0 ? &pm_domain_cpu_gov : NULL;
+
+	ret = pm_genpd_init(pd, pd_gov, false);
+	if (ret) {
+		psci_pd_free_states(states, state_count);
+		goto free_name;
+	}
+
+	ret = of_genpd_add_provider_simple(np, pd);
+	if (ret)
+		goto remove_pd;
+
+	pd_provider->node = of_node_get(np);
+	list_add(&pd_provider->link, &psci_pd_providers);
+
+	pr_debug("init PM domain %s\n", pd->name);
+	return 0;
+
+remove_pd:
+	pm_genpd_remove(pd);
+free_name:
+	kfree(pd->name);
+free_pd_prov:
+	kfree(pd_provider);
+free_pd:
+	kfree(pd);
+out:
+	pr_err("failed to init PM domain ret=%d %pOF\n", ret, np);
+	return ret;
+}
+
+static void __init psci_pd_remove(void)
+{
+	struct psci_pd_provider *pd_provider, *it;
+	struct generic_pm_domain *genpd;
+
+	list_for_each_entry_safe(pd_provider, it, &psci_pd_providers, link) {
+		of_genpd_del_provider(pd_provider->node);
+
+		genpd = of_genpd_remove_last(pd_provider->node);
+		if (!IS_ERR(genpd))
+			kfree(genpd);
+
+		of_node_put(pd_provider->node);
+		list_del(&pd_provider->link);
+		kfree(pd_provider);
+	}
+}
+
+static int __init psci_pd_init_topology(struct device_node *np)
+{
+	struct device_node *node;
+	struct of_phandle_args child, parent;
+	int ret;
+
+	for_each_child_of_node(np, node) {
+		if (of_parse_phandle_with_args(node, "power-domains",
+					"#power-domain-cells", 0, &parent))
+			continue;
+
+		child.np = node;
+		child.args_count = 0;
+
+		ret = of_genpd_add_subdomain(&parent, &child);
+		of_node_put(parent.np);
+		if (ret) {
+			of_node_put(node);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static const struct of_device_id psci_of_match[] __initconst = {
+	{ .compatible = "arm,psci" },
+	{ .compatible = "arm,psci-0.2" },
+	{ .compatible = "arm,psci-1.0" },
+	{}
+};
+
+static int __init psci_idle_init_domains(void)
+{
+	struct device_node *np = of_find_matching_node(NULL, psci_of_match);
+	struct device_node *node;
+	int ret = 0, pd_count = 0;
+
+	if (!np)
+		return -ENODEV;
+
+	/* Currently limit the hierarchical topology to be used in OSI mode. */
+	if (!psci_has_osi_support())
+		goto out;
+
+	/*
+	 * Parse child nodes for the "#power-domain-cells" property and
+	 * initialize a genpd/genpd-of-provider pair when it's found.
+	 */
+	for_each_child_of_node(np, node) {
+		if (!of_find_property(node, "#power-domain-cells", NULL))
+			continue;
+
+		ret = psci_pd_init(node);
+		if (ret)
+			goto put_node;
+
+		pd_count++;
+	}
+
+	/* Bail out if not using the hierarchical CPU topology. */
+	if (!pd_count)
+		goto out;
+
+	/* Link genpd masters/subdomains to model the CPU topology. */
+	ret = psci_pd_init_topology(np);
+	if (ret)
+		goto remove_pd;
+
+	/* Try to enable OSI mode. */
+	ret = psci_set_osi_mode();
+	if (ret)
+		pr_warn("failed to enable OSI mode: %d\n", ret);
+	else
+		osi_mode_enabled = true;
+
+	of_node_put(np);
+	pr_info("Initialized CPU PM domain topology\n");
+	return pd_count;
+
+put_node:
+	of_node_put(node);
+remove_pd:
+	if (pd_count)
+		psci_pd_remove();
+	pr_err("failed to create CPU PM domains ret=%d\n", ret);
+out:
+	of_node_put(np);
+	return ret;
+}
+subsys_initcall(psci_idle_init_domains);
+
 struct device *psci_dt_attach_cpu(int cpu)
 {
 	struct device *dev;
diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c
index 34a89d99bb0f..70141090a298 100644
--- a/drivers/cpuidle/cpuidle-psci.c
+++ b/drivers/cpuidle/cpuidle-psci.c
@@ -34,7 +34,7 @@ static DEFINE_PER_CPU_READ_MOSTLY(struct psci_cpuidle_data, psci_cpuidle_data);
 static DEFINE_PER_CPU(u32, domain_state);
 static bool psci_cpuidle_use_cpuhp;
 
-static inline void psci_set_domain_state(u32 state)
+void psci_set_domain_state(u32 state)
 {
 	__this_cpu_write(domain_state, state);
 }
@@ -143,7 +143,7 @@ static const struct of_device_id psci_idle_state_match[] __initconst = {
 	{ },
 };
 
-static int __init psci_dt_parse_state_node(struct device_node *np, u32 *state)
+int __init psci_dt_parse_state_node(struct device_node *np, u32 *state)
 {
 	int err = of_property_read_u32(np, "arm,psci-suspend-param", state);
 
diff --git a/drivers/cpuidle/cpuidle-psci.h b/drivers/cpuidle/cpuidle-psci.h
index 0cadbb71dc55..d2e55cad9ac6 100644
--- a/drivers/cpuidle/cpuidle-psci.h
+++ b/drivers/cpuidle/cpuidle-psci.h
@@ -3,6 +3,11 @@
 #ifndef __CPUIDLE_PSCI_H
 #define __CPUIDLE_PSCI_H
 
+struct device_node;
+
+void psci_set_domain_state(u32 state);
+int __init psci_dt_parse_state_node(struct device_node *np, u32 *state);
+
 #ifdef CONFIG_PM_GENERIC_DOMAINS_OF
 struct device *psci_dt_attach_cpu(int cpu);
 #else
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 13/14] cpuidle: psci: Add support for PM domains by using genpd
@ 2019-12-11 15:43   ` Ulf Hansson
  0 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-11 15:43 UTC (permalink / raw)
  To: Sudeep Holla, Lorenzo Pieralisi, Rob Herring, linux-pm
  Cc: Mark Rutland, Ulf Hansson, Kevin Hilman, Stephen Boyd,
	linux-arm-msm, Daniel Lezcano, Rafael J . Wysocki, Lina Iyer,
	Bjorn Andersson, Andy Gross, Lina Iyer, linux-arm-kernel

When the hierarchical CPU topology layout is used in DT and the PSCI OSI
mode is supported by the PSCI FW, let's initialize a corresponding PM
domain topology by using genpd. This enables a CPU and a group of CPUs,
when attached to the topology, to be power-managed accordingly.

To trigger the attempt to initialize the genpd data structures let's use a
subsys_initcall, which should be early enough to allow CPUs, but also other
devices to be attached.

The initialization consists of parsing the PSCI OF node for the topology
and the "domain idle states" DT bindings. In case the idle states are
compatible with "domain-idle-state", the initialized genpd becomes
responsible of selecting an idle state for the PM domain, via assigning it
a genpd governor.

Note that, a successful initialization of the genpd data structures, is
followed by a call to psci_set_osi_mode(), as to try to enable the OSI mode
in the PSCI FW. In case this fails, we fall back into a degraded mode
rather than bailing out and returning an error code.

Co-developed-by: Lina Iyer <lina.iyer@linaro.org>
Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---

Changes in v4:
	- None.

---
 drivers/cpuidle/cpuidle-psci-domain.c | 267 ++++++++++++++++++++++++++
 drivers/cpuidle/cpuidle-psci.c        |   4 +-
 drivers/cpuidle/cpuidle-psci.h        |   5 +
 3 files changed, 274 insertions(+), 2 deletions(-)

diff --git a/drivers/cpuidle/cpuidle-psci-domain.c b/drivers/cpuidle/cpuidle-psci-domain.c
index 656ef3d59149..c2f94ba42222 100644
--- a/drivers/cpuidle/cpuidle-psci-domain.c
+++ b/drivers/cpuidle/cpuidle-psci-domain.c
@@ -7,14 +7,281 @@
  *
  */
 
+#define pr_fmt(fmt) "CPUidle PSCI: " fmt
+
 #include <linux/cpu.h>
 #include <linux/device.h>
 #include <linux/kernel.h>
 #include <linux/pm_domain.h>
 #include <linux/pm_runtime.h>
+#include <linux/psci.h>
+#include <linux/slab.h>
+#include <linux/string.h>
 
 #include "cpuidle-psci.h"
 
+struct psci_pd_provider {
+	struct list_head link;
+	struct device_node *node;
+};
+
+static LIST_HEAD(psci_pd_providers);
+static bool osi_mode_enabled;
+
+static int psci_pd_power_off(struct generic_pm_domain *pd)
+{
+	struct genpd_power_state *state = &pd->states[pd->state_idx];
+	u32 *pd_state;
+
+	/* If we have failed to enable OSI mode, then abort power off. */
+	if (!osi_mode_enabled)
+		return -EBUSY;
+
+	if (!state->data)
+		return 0;
+
+	/* OSI mode is enabled, set the corresponding domain state. */
+	pd_state = state->data;
+	psci_set_domain_state(*pd_state);
+
+	return 0;
+}
+
+static int __init psci_pd_parse_state_nodes(struct genpd_power_state *states,
+					int state_count)
+{
+	int i, ret;
+	u32 psci_state, *psci_state_buf;
+
+	for (i = 0; i < state_count; i++) {
+		ret = psci_dt_parse_state_node(to_of_node(states[i].fwnode),
+					&psci_state);
+		if (ret)
+			goto free_state;
+
+		psci_state_buf = kmalloc(sizeof(u32), GFP_KERNEL);
+		if (!psci_state_buf) {
+			ret = -ENOMEM;
+			goto free_state;
+		}
+		*psci_state_buf = psci_state;
+		states[i].data = psci_state_buf;
+	}
+
+	return 0;
+
+free_state:
+	i--;
+	for (; i >= 0; i--)
+		kfree(states[i].data);
+	return ret;
+}
+
+static int __init psci_pd_parse_states(struct device_node *np,
+			struct genpd_power_state **states, int *state_count)
+{
+	int ret;
+
+	/* Parse the domain idle states. */
+	ret = of_genpd_parse_idle_states(np, states, state_count);
+	if (ret)
+		return ret;
+
+	/* Fill out the PSCI specifics for each found state. */
+	ret = psci_pd_parse_state_nodes(*states, *state_count);
+	if (ret)
+		kfree(*states);
+
+	return ret;
+}
+
+static void psci_pd_free_states(struct genpd_power_state *states,
+				unsigned int state_count)
+{
+	int i;
+
+	for (i = 0; i < state_count; i++)
+		kfree(states[i].data);
+	kfree(states);
+}
+
+static int __init psci_pd_init(struct device_node *np)
+{
+	struct generic_pm_domain *pd;
+	struct psci_pd_provider *pd_provider;
+	struct dev_power_governor *pd_gov;
+	struct genpd_power_state *states = NULL;
+	int ret = -ENOMEM, state_count = 0;
+
+	pd = kzalloc(sizeof(*pd), GFP_KERNEL);
+	if (!pd)
+		goto out;
+
+	pd_provider = kzalloc(sizeof(*pd_provider), GFP_KERNEL);
+	if (!pd_provider)
+		goto free_pd;
+
+	pd->name = kasprintf(GFP_KERNEL, "%pOF", np);
+	if (!pd->name)
+		goto free_pd_prov;
+
+	/*
+	 * Parse the domain idle states and let genpd manage the state selection
+	 * for those being compatible with "domain-idle-state".
+	 */
+	ret = psci_pd_parse_states(np, &states, &state_count);
+	if (ret)
+		goto free_name;
+
+	pd->free_states = psci_pd_free_states;
+	pd->name = kbasename(pd->name);
+	pd->power_off = psci_pd_power_off;
+	pd->states = states;
+	pd->state_count = state_count;
+	pd->flags |= GENPD_FLAG_IRQ_SAFE | GENPD_FLAG_CPU_DOMAIN;
+
+	/* Use governor for CPU PM domains if it has some states to manage. */
+	pd_gov = state_count > 0 ? &pm_domain_cpu_gov : NULL;
+
+	ret = pm_genpd_init(pd, pd_gov, false);
+	if (ret) {
+		psci_pd_free_states(states, state_count);
+		goto free_name;
+	}
+
+	ret = of_genpd_add_provider_simple(np, pd);
+	if (ret)
+		goto remove_pd;
+
+	pd_provider->node = of_node_get(np);
+	list_add(&pd_provider->link, &psci_pd_providers);
+
+	pr_debug("init PM domain %s\n", pd->name);
+	return 0;
+
+remove_pd:
+	pm_genpd_remove(pd);
+free_name:
+	kfree(pd->name);
+free_pd_prov:
+	kfree(pd_provider);
+free_pd:
+	kfree(pd);
+out:
+	pr_err("failed to init PM domain ret=%d %pOF\n", ret, np);
+	return ret;
+}
+
+static void __init psci_pd_remove(void)
+{
+	struct psci_pd_provider *pd_provider, *it;
+	struct generic_pm_domain *genpd;
+
+	list_for_each_entry_safe(pd_provider, it, &psci_pd_providers, link) {
+		of_genpd_del_provider(pd_provider->node);
+
+		genpd = of_genpd_remove_last(pd_provider->node);
+		if (!IS_ERR(genpd))
+			kfree(genpd);
+
+		of_node_put(pd_provider->node);
+		list_del(&pd_provider->link);
+		kfree(pd_provider);
+	}
+}
+
+static int __init psci_pd_init_topology(struct device_node *np)
+{
+	struct device_node *node;
+	struct of_phandle_args child, parent;
+	int ret;
+
+	for_each_child_of_node(np, node) {
+		if (of_parse_phandle_with_args(node, "power-domains",
+					"#power-domain-cells", 0, &parent))
+			continue;
+
+		child.np = node;
+		child.args_count = 0;
+
+		ret = of_genpd_add_subdomain(&parent, &child);
+		of_node_put(parent.np);
+		if (ret) {
+			of_node_put(node);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static const struct of_device_id psci_of_match[] __initconst = {
+	{ .compatible = "arm,psci" },
+	{ .compatible = "arm,psci-0.2" },
+	{ .compatible = "arm,psci-1.0" },
+	{}
+};
+
+static int __init psci_idle_init_domains(void)
+{
+	struct device_node *np = of_find_matching_node(NULL, psci_of_match);
+	struct device_node *node;
+	int ret = 0, pd_count = 0;
+
+	if (!np)
+		return -ENODEV;
+
+	/* Currently limit the hierarchical topology to be used in OSI mode. */
+	if (!psci_has_osi_support())
+		goto out;
+
+	/*
+	 * Parse child nodes for the "#power-domain-cells" property and
+	 * initialize a genpd/genpd-of-provider pair when it's found.
+	 */
+	for_each_child_of_node(np, node) {
+		if (!of_find_property(node, "#power-domain-cells", NULL))
+			continue;
+
+		ret = psci_pd_init(node);
+		if (ret)
+			goto put_node;
+
+		pd_count++;
+	}
+
+	/* Bail out if not using the hierarchical CPU topology. */
+	if (!pd_count)
+		goto out;
+
+	/* Link genpd masters/subdomains to model the CPU topology. */
+	ret = psci_pd_init_topology(np);
+	if (ret)
+		goto remove_pd;
+
+	/* Try to enable OSI mode. */
+	ret = psci_set_osi_mode();
+	if (ret)
+		pr_warn("failed to enable OSI mode: %d\n", ret);
+	else
+		osi_mode_enabled = true;
+
+	of_node_put(np);
+	pr_info("Initialized CPU PM domain topology\n");
+	return pd_count;
+
+put_node:
+	of_node_put(node);
+remove_pd:
+	if (pd_count)
+		psci_pd_remove();
+	pr_err("failed to create CPU PM domains ret=%d\n", ret);
+out:
+	of_node_put(np);
+	return ret;
+}
+subsys_initcall(psci_idle_init_domains);
+
 struct device *psci_dt_attach_cpu(int cpu)
 {
 	struct device *dev;
diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c
index 34a89d99bb0f..70141090a298 100644
--- a/drivers/cpuidle/cpuidle-psci.c
+++ b/drivers/cpuidle/cpuidle-psci.c
@@ -34,7 +34,7 @@ static DEFINE_PER_CPU_READ_MOSTLY(struct psci_cpuidle_data, psci_cpuidle_data);
 static DEFINE_PER_CPU(u32, domain_state);
 static bool psci_cpuidle_use_cpuhp;
 
-static inline void psci_set_domain_state(u32 state)
+void psci_set_domain_state(u32 state)
 {
 	__this_cpu_write(domain_state, state);
 }
@@ -143,7 +143,7 @@ static const struct of_device_id psci_idle_state_match[] __initconst = {
 	{ },
 };
 
-static int __init psci_dt_parse_state_node(struct device_node *np, u32 *state)
+int __init psci_dt_parse_state_node(struct device_node *np, u32 *state)
 {
 	int err = of_property_read_u32(np, "arm,psci-suspend-param", state);
 
diff --git a/drivers/cpuidle/cpuidle-psci.h b/drivers/cpuidle/cpuidle-psci.h
index 0cadbb71dc55..d2e55cad9ac6 100644
--- a/drivers/cpuidle/cpuidle-psci.h
+++ b/drivers/cpuidle/cpuidle-psci.h
@@ -3,6 +3,11 @@
 #ifndef __CPUIDLE_PSCI_H
 #define __CPUIDLE_PSCI_H
 
+struct device_node;
+
+void psci_set_domain_state(u32 state);
+int __init psci_dt_parse_state_node(struct device_node *np, u32 *state);
+
 #ifdef CONFIG_PM_GENERIC_DOMAINS_OF
 struct device *psci_dt_attach_cpu(int cpu);
 #else
-- 
2.17.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 14/14] arm64: dts: Convert to the hierarchical CPU topology layout for MSM8916
  2019-12-11 15:43 ` Ulf Hansson
@ 2019-12-11 15:43   ` Ulf Hansson
  -1 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-11 15:43 UTC (permalink / raw)
  To: Sudeep Holla, Lorenzo Pieralisi, Rob Herring, linux-pm
  Cc: Rafael J . Wysocki, Daniel Lezcano, Mark Rutland, Lina Iyer,
	Vincent Guittot, Stephen Boyd, Andy Gross, Bjorn Andersson,
	Kevin Hilman, Ulf Hansson, linux-arm-kernel, linux-arm-msm,
	Lina Iyer

To enable the OS to better support PSCI OS initiated CPU suspend mode,
let's convert from the flattened layout to the hierarchical layout.

In the hierarchical layout, let's create a power domain provider per CPU
and describe the idle states for each CPU inside the power domain provider
node. To group the CPUs into a cluster, let's add another power domain
provider and make it act as the master domain. Note that, the CPU's idle
states remains compatible with "arm,idle-state", while the cluster's idle
state becomes compatible with "domain-idle-state".

Co-developed-by: Lina Iyer <lina.iyer@linaro.org>
Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---

Changes in v4:
	- None.

---
 arch/arm64/boot/dts/qcom/msm8916.dtsi | 57 +++++++++++++++++++++++++--
 1 file changed, 53 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
index 8686e101905c..282c36c8fa3b 100644
--- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
@@ -102,10 +102,11 @@
 			reg = <0x0>;
 			next-level-cache = <&L2_0>;
 			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0>;
 			clocks = <&apcs>;
 			operating-points-v2 = <&cpu_opp_table>;
 			#cooling-cells = <2>;
+			power-domains = <&CPU_PD0>;
+			power-domain-names = "psci";
 		};
 
 		CPU1: cpu@1 {
@@ -114,10 +115,11 @@
 			reg = <0x1>;
 			next-level-cache = <&L2_0>;
 			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0>;
 			clocks = <&apcs>;
 			operating-points-v2 = <&cpu_opp_table>;
 			#cooling-cells = <2>;
+			power-domains = <&CPU_PD1>;
+			power-domain-names = "psci";
 		};
 
 		CPU2: cpu@2 {
@@ -126,10 +128,11 @@
 			reg = <0x2>;
 			next-level-cache = <&L2_0>;
 			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0>;
 			clocks = <&apcs>;
 			operating-points-v2 = <&cpu_opp_table>;
 			#cooling-cells = <2>;
+			power-domains = <&CPU_PD2>;
+			power-domain-names = "psci";
 		};
 
 		CPU3: cpu@3 {
@@ -138,10 +141,11 @@
 			reg = <0x3>;
 			next-level-cache = <&L2_0>;
 			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0>;
 			clocks = <&apcs>;
 			operating-points-v2 = <&cpu_opp_table>;
 			#cooling-cells = <2>;
+			power-domains = <&CPU_PD3>;
+			power-domain-names = "psci";
 		};
 
 		L2_0: l2-cache {
@@ -161,12 +165,57 @@
 				min-residency-us = <2000>;
 				local-timer-stop;
 			};
+
+			CLUSTER_RET: cluster-retention {
+				compatible = "domain-idle-state";
+				arm,psci-suspend-param = <0x41000012>;
+				entry-latency-us = <500>;
+				exit-latency-us = <500>;
+				min-residency-us = <2000>;
+			};
+
+			CLUSTER_PWRDN: cluster-gdhs {
+				compatible = "domain-idle-state";
+				arm,psci-suspend-param = <0x41000032>;
+				entry-latency-us = <2000>;
+				exit-latency-us = <2000>;
+				min-residency-us = <6000>;
+			};
 		};
 	};
 
 	psci {
 		compatible = "arm,psci-1.0";
 		method = "smc";
+
+		CPU_PD0: cpu-pd0 {
+			#power-domain-cells = <0>;
+			power-domains = <&CLUSTER_PD>;
+			domain-idle-states = <&CPU_SLEEP_0>;
+		};
+
+		CPU_PD1: cpu-pd1 {
+			#power-domain-cells = <0>;
+			power-domains = <&CLUSTER_PD>;
+			domain-idle-states = <&CPU_SLEEP_0>;
+		};
+
+		CPU_PD2: cpu-pd2 {
+			#power-domain-cells = <0>;
+			power-domains = <&CLUSTER_PD>;
+			domain-idle-states = <&CPU_SLEEP_0>;
+		};
+
+		CPU_PD3: cpu-pd3 {
+			#power-domain-cells = <0>;
+			power-domains = <&CLUSTER_PD>;
+			domain-idle-states = <&CPU_SLEEP_0>;
+		};
+
+		CLUSTER_PD: cluster-pd {
+			#power-domain-cells = <0>;
+			domain-idle-states = <&CLUSTER_RET>, <&CLUSTER_PWRDN>;
+		};
 	};
 
 	pmu {
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v4 14/14] arm64: dts: Convert to the hierarchical CPU topology layout for MSM8916
@ 2019-12-11 15:43   ` Ulf Hansson
  0 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-11 15:43 UTC (permalink / raw)
  To: Sudeep Holla, Lorenzo Pieralisi, Rob Herring, linux-pm
  Cc: Mark Rutland, Ulf Hansson, Kevin Hilman, Stephen Boyd,
	linux-arm-msm, Daniel Lezcano, Rafael J . Wysocki, Lina Iyer,
	Bjorn Andersson, Andy Gross, Lina Iyer, linux-arm-kernel

To enable the OS to better support PSCI OS initiated CPU suspend mode,
let's convert from the flattened layout to the hierarchical layout.

In the hierarchical layout, let's create a power domain provider per CPU
and describe the idle states for each CPU inside the power domain provider
node. To group the CPUs into a cluster, let's add another power domain
provider and make it act as the master domain. Note that, the CPU's idle
states remains compatible with "arm,idle-state", while the cluster's idle
state becomes compatible with "domain-idle-state".

Co-developed-by: Lina Iyer <lina.iyer@linaro.org>
Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---

Changes in v4:
	- None.

---
 arch/arm64/boot/dts/qcom/msm8916.dtsi | 57 +++++++++++++++++++++++++--
 1 file changed, 53 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
index 8686e101905c..282c36c8fa3b 100644
--- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
@@ -102,10 +102,11 @@
 			reg = <0x0>;
 			next-level-cache = <&L2_0>;
 			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0>;
 			clocks = <&apcs>;
 			operating-points-v2 = <&cpu_opp_table>;
 			#cooling-cells = <2>;
+			power-domains = <&CPU_PD0>;
+			power-domain-names = "psci";
 		};
 
 		CPU1: cpu@1 {
@@ -114,10 +115,11 @@
 			reg = <0x1>;
 			next-level-cache = <&L2_0>;
 			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0>;
 			clocks = <&apcs>;
 			operating-points-v2 = <&cpu_opp_table>;
 			#cooling-cells = <2>;
+			power-domains = <&CPU_PD1>;
+			power-domain-names = "psci";
 		};
 
 		CPU2: cpu@2 {
@@ -126,10 +128,11 @@
 			reg = <0x2>;
 			next-level-cache = <&L2_0>;
 			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0>;
 			clocks = <&apcs>;
 			operating-points-v2 = <&cpu_opp_table>;
 			#cooling-cells = <2>;
+			power-domains = <&CPU_PD2>;
+			power-domain-names = "psci";
 		};
 
 		CPU3: cpu@3 {
@@ -138,10 +141,11 @@
 			reg = <0x3>;
 			next-level-cache = <&L2_0>;
 			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0>;
 			clocks = <&apcs>;
 			operating-points-v2 = <&cpu_opp_table>;
 			#cooling-cells = <2>;
+			power-domains = <&CPU_PD3>;
+			power-domain-names = "psci";
 		};
 
 		L2_0: l2-cache {
@@ -161,12 +165,57 @@
 				min-residency-us = <2000>;
 				local-timer-stop;
 			};
+
+			CLUSTER_RET: cluster-retention {
+				compatible = "domain-idle-state";
+				arm,psci-suspend-param = <0x41000012>;
+				entry-latency-us = <500>;
+				exit-latency-us = <500>;
+				min-residency-us = <2000>;
+			};
+
+			CLUSTER_PWRDN: cluster-gdhs {
+				compatible = "domain-idle-state";
+				arm,psci-suspend-param = <0x41000032>;
+				entry-latency-us = <2000>;
+				exit-latency-us = <2000>;
+				min-residency-us = <6000>;
+			};
 		};
 	};
 
 	psci {
 		compatible = "arm,psci-1.0";
 		method = "smc";
+
+		CPU_PD0: cpu-pd0 {
+			#power-domain-cells = <0>;
+			power-domains = <&CLUSTER_PD>;
+			domain-idle-states = <&CPU_SLEEP_0>;
+		};
+
+		CPU_PD1: cpu-pd1 {
+			#power-domain-cells = <0>;
+			power-domains = <&CLUSTER_PD>;
+			domain-idle-states = <&CPU_SLEEP_0>;
+		};
+
+		CPU_PD2: cpu-pd2 {
+			#power-domain-cells = <0>;
+			power-domains = <&CLUSTER_PD>;
+			domain-idle-states = <&CPU_SLEEP_0>;
+		};
+
+		CPU_PD3: cpu-pd3 {
+			#power-domain-cells = <0>;
+			power-domains = <&CLUSTER_PD>;
+			domain-idle-states = <&CPU_SLEEP_0>;
+		};
+
+		CLUSTER_PD: cluster-pd {
+			#power-domain-cells = <0>;
+			domain-idle-states = <&CLUSTER_RET>, <&CLUSTER_PWRDN>;
+		};
 	};
 
 	pmu {
-- 
2.17.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 00/14] cpuidle: psci: Support hierarchical CPU arrangement
  2019-12-11 15:43 ` Ulf Hansson
@ 2019-12-18  7:36   ` Ulf Hansson
  -1 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-18  7:36 UTC (permalink / raw)
  To: Sudeep Holla, Lorenzo Pieralisi, Linux PM
  Cc: Rafael J . Wysocki, Daniel Lezcano, Rob Herring, Mark Rutland,
	Lina Iyer, Vincent Guittot, Stephen Boyd, Andy Gross,
	Bjorn Andersson, Kevin Hilman, Linux ARM, linux-arm-msm

Sudeep, Lorenzo,

On Wed, 11 Dec 2019 at 16:43, Ulf Hansson <ulf.hansson@linaro.org> wrote:
>
> Changes in v4:
>         - Mover the check for OSI support from psci_dt_attach_cpu() to the
>         caller's side of it.
>         - Add comment in the code about using the deepest idle state as the
>         triggering point for the domain state selection.
>         - Folded in a patch to enable support for CPU hotplug.

I believe I should have addressed all your provided inputs for this
version, unless you find something new, of course.

Then, would it be possible to get your blessing for this, before
Christmas, to allow this to cook for a while in linux-next via
Rafael's tree?

Kind regards
Uffe

>
> Changes in v3:
>         - Take one step further to completely avoid executing any OSI specific
>         code from the ->enter() callback, while operating in the default PSCI
>         Platform Coordinated mode.
>         - Update example for the PSCI DT bindings to make it compile with
>         "make dt_binding_check"
>
> Changes in v2:
>         - Avoid to affect the non-OSI path with specific changes for OSI. This
>         forced me to re-order the series and a caused more or less minor changes
>         to most of the patches.
>         - Updated the DT bindings for PSCI to clarify and to include the "psci"
>         name of the PM domain to attach to.
>         - Replaced patch1 with another patch from Sudeep, solving the same
>         problem, but in a different way.
>
> This series enables initial support for hierarchical CPU arrangement, managed
> by PSCI and its corresponding cpuidle driver. It's based on using the generic
> PM domain (genpd), which nowadays also supports devices belonging to CPUs.
>
> The last DTS patch enables the hierarchical topology to be used for the Qcom
> 410c Dragonboard, which supports the PSCI OS-initiated mode.
>
> More detailed background can be found from previous submissions [1].
>
> The series is also available at:
> git.linaro.org/people/ulf.hansson/linux-pm.git next
>
> Kind regards
> Ulf Hansson
>
> [1]
> https://lwn.net/Articles/788306/
>
>
> Lina Iyer (1):
>   cpuidle: dt: Support hierarchical CPU idle states
>
> Sudeep Holla (1):
>   cpuidle: psci: Align psci_power_state count with idle state count
>
> Ulf Hansson (12):
>   dt: psci: Update DT bindings to support hierarchical PSCI states
>   firmware: psci: Export functions to manage the OSI mode
>   of: base: Add of_get_cpu_state_node() to get idle states for a CPU
>     node
>   cpuidle: psci: Simplify OF parsing of CPU idle state nodes
>   cpuidle: psci: Support hierarchical CPU idle states
>   cpuidle: psci: Add a helper to attach a CPU to its PM domain
>   cpuidle: psci: Attach CPU devices to their PM domains
>   cpuidle: psci: Prepare to use OS initiated suspend mode via PM domains
>   cpuidle: psci: Manage runtime PM in the idle path
>   cpuidle: psci: Support CPU hotplug for the hierarchical model
>   cpuidle: psci: Add support for PM domains by using genpd
>   arm64: dts: Convert to the hierarchical CPU topology layout for
>     MSM8916
>
>  .../devicetree/bindings/arm/cpus.yaml         |  15 +
>  .../devicetree/bindings/arm/psci.yaml         | 104 ++++++
>  arch/arm64/boot/dts/qcom/msm8916.dtsi         |  57 +++-
>  drivers/cpuidle/Makefile                      |   4 +-
>  drivers/cpuidle/cpuidle-psci-domain.c         | 298 ++++++++++++++++++
>  drivers/cpuidle/cpuidle-psci.c                | 161 ++++++++--
>  drivers/cpuidle/cpuidle-psci.h                |  17 +
>  drivers/cpuidle/dt_idle_states.c              |   5 +-
>  drivers/firmware/psci/psci.c                  |  18 +-
>  drivers/of/base.c                             |  36 +++
>  include/linux/cpuhotplug.h                    |   1 +
>  include/linux/of.h                            |   8 +
>  include/linux/psci.h                          |   2 +
>  13 files changed, 691 insertions(+), 35 deletions(-)
>  create mode 100644 drivers/cpuidle/cpuidle-psci-domain.c
>  create mode 100644 drivers/cpuidle/cpuidle-psci.h
>
> --
> 2.17.1
>

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 00/14] cpuidle: psci: Support hierarchical CPU arrangement
@ 2019-12-18  7:36   ` Ulf Hansson
  0 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-18  7:36 UTC (permalink / raw)
  To: Sudeep Holla, Lorenzo Pieralisi, Linux PM
  Cc: Mark Rutland, Kevin Hilman, Stephen Boyd, linux-arm-msm,
	Daniel Lezcano, Rafael J . Wysocki, Andy Gross, Lina Iyer,
	Bjorn Andersson, Rob Herring, Linux ARM

Sudeep, Lorenzo,

On Wed, 11 Dec 2019 at 16:43, Ulf Hansson <ulf.hansson@linaro.org> wrote:
>
> Changes in v4:
>         - Mover the check for OSI support from psci_dt_attach_cpu() to the
>         caller's side of it.
>         - Add comment in the code about using the deepest idle state as the
>         triggering point for the domain state selection.
>         - Folded in a patch to enable support for CPU hotplug.

I believe I should have addressed all your provided inputs for this
version, unless you find something new, of course.

Then, would it be possible to get your blessing for this, before
Christmas, to allow this to cook for a while in linux-next via
Rafael's tree?

Kind regards
Uffe

>
> Changes in v3:
>         - Take one step further to completely avoid executing any OSI specific
>         code from the ->enter() callback, while operating in the default PSCI
>         Platform Coordinated mode.
>         - Update example for the PSCI DT bindings to make it compile with
>         "make dt_binding_check"
>
> Changes in v2:
>         - Avoid to affect the non-OSI path with specific changes for OSI. This
>         forced me to re-order the series and a caused more or less minor changes
>         to most of the patches.
>         - Updated the DT bindings for PSCI to clarify and to include the "psci"
>         name of the PM domain to attach to.
>         - Replaced patch1 with another patch from Sudeep, solving the same
>         problem, but in a different way.
>
> This series enables initial support for hierarchical CPU arrangement, managed
> by PSCI and its corresponding cpuidle driver. It's based on using the generic
> PM domain (genpd), which nowadays also supports devices belonging to CPUs.
>
> The last DTS patch enables the hierarchical topology to be used for the Qcom
> 410c Dragonboard, which supports the PSCI OS-initiated mode.
>
> More detailed background can be found from previous submissions [1].
>
> The series is also available at:
> git.linaro.org/people/ulf.hansson/linux-pm.git next
>
> Kind regards
> Ulf Hansson
>
> [1]
> https://lwn.net/Articles/788306/
>
>
> Lina Iyer (1):
>   cpuidle: dt: Support hierarchical CPU idle states
>
> Sudeep Holla (1):
>   cpuidle: psci: Align psci_power_state count with idle state count
>
> Ulf Hansson (12):
>   dt: psci: Update DT bindings to support hierarchical PSCI states
>   firmware: psci: Export functions to manage the OSI mode
>   of: base: Add of_get_cpu_state_node() to get idle states for a CPU
>     node
>   cpuidle: psci: Simplify OF parsing of CPU idle state nodes
>   cpuidle: psci: Support hierarchical CPU idle states
>   cpuidle: psci: Add a helper to attach a CPU to its PM domain
>   cpuidle: psci: Attach CPU devices to their PM domains
>   cpuidle: psci: Prepare to use OS initiated suspend mode via PM domains
>   cpuidle: psci: Manage runtime PM in the idle path
>   cpuidle: psci: Support CPU hotplug for the hierarchical model
>   cpuidle: psci: Add support for PM domains by using genpd
>   arm64: dts: Convert to the hierarchical CPU topology layout for
>     MSM8916
>
>  .../devicetree/bindings/arm/cpus.yaml         |  15 +
>  .../devicetree/bindings/arm/psci.yaml         | 104 ++++++
>  arch/arm64/boot/dts/qcom/msm8916.dtsi         |  57 +++-
>  drivers/cpuidle/Makefile                      |   4 +-
>  drivers/cpuidle/cpuidle-psci-domain.c         | 298 ++++++++++++++++++
>  drivers/cpuidle/cpuidle-psci.c                | 161 ++++++++--
>  drivers/cpuidle/cpuidle-psci.h                |  17 +
>  drivers/cpuidle/dt_idle_states.c              |   5 +-
>  drivers/firmware/psci/psci.c                  |  18 +-
>  drivers/of/base.c                             |  36 +++
>  include/linux/cpuhotplug.h                    |   1 +
>  include/linux/of.h                            |   8 +
>  include/linux/psci.h                          |   2 +
>  13 files changed, 691 insertions(+), 35 deletions(-)
>  create mode 100644 drivers/cpuidle/cpuidle-psci-domain.c
>  create mode 100644 drivers/cpuidle/cpuidle-psci.h
>
> --
> 2.17.1
>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 00/14] cpuidle: psci: Support hierarchical CPU arrangement
  2019-12-18  7:36   ` Ulf Hansson
@ 2019-12-18 10:25     ` Sudeep Holla
  -1 siblings, 0 replies; 76+ messages in thread
From: Sudeep Holla @ 2019-12-18 10:25 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Lorenzo Pieralisi, Linux PM, Rafael J . Wysocki, Daniel Lezcano,
	Rob Herring, Mark Rutland, Lina Iyer, Vincent Guittot,
	Stephen Boyd, Andy Gross, Bjorn Andersson, Kevin Hilman,
	Linux ARM, linux-arm-msm, Sudeep Holla

On Wed, Dec 18, 2019 at 08:36:38AM +0100, Ulf Hansson wrote:
> Sudeep, Lorenzo,
>
> On Wed, 11 Dec 2019 at 16:43, Ulf Hansson <ulf.hansson@linaro.org> wrote:
> >
> > Changes in v4:
> >         - Mover the check for OSI support from psci_dt_attach_cpu() to the
> >         caller's side of it.
> >         - Add comment in the code about using the deepest idle state as the
> >         triggering point for the domain state selection.
> >         - Folded in a patch to enable support for CPU hotplug.
>
> I believe I should have addressed all your provided inputs for this
> version, unless you find something new, of course.
>

I have marked this for a review before this Christmas, Lorenzo is off for
a while but he has mentioned to me few things to look for. I will do so
before Christmas for sure. Sorry for the delay.

--
Regards,
Sudeep

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 00/14] cpuidle: psci: Support hierarchical CPU arrangement
@ 2019-12-18 10:25     ` Sudeep Holla
  0 siblings, 0 replies; 76+ messages in thread
From: Sudeep Holla @ 2019-12-18 10:25 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Mark Rutland, Lorenzo Pieralisi, Linux PM, Stephen Boyd,
	linux-arm-msm, Daniel Lezcano, Rafael J . Wysocki, Andy Gross,
	Lina Iyer, Bjorn Andersson, Kevin Hilman, Rob Herring,
	Sudeep Holla, Linux ARM

On Wed, Dec 18, 2019 at 08:36:38AM +0100, Ulf Hansson wrote:
> Sudeep, Lorenzo,
>
> On Wed, 11 Dec 2019 at 16:43, Ulf Hansson <ulf.hansson@linaro.org> wrote:
> >
> > Changes in v4:
> >         - Mover the check for OSI support from psci_dt_attach_cpu() to the
> >         caller's side of it.
> >         - Add comment in the code about using the deepest idle state as the
> >         triggering point for the domain state selection.
> >         - Folded in a patch to enable support for CPU hotplug.
>
> I believe I should have addressed all your provided inputs for this
> version, unless you find something new, of course.
>

I have marked this for a review before this Christmas, Lorenzo is off for
a while but he has mentioned to me few things to look for. I will do so
before Christmas for sure. Sorry for the delay.

--
Regards,
Sudeep

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 08/14] cpuidle: psci: Add a helper to attach a CPU to its PM domain
  2019-12-11 15:43   ` Ulf Hansson
@ 2019-12-19 14:30     ` Sudeep Holla
  -1 siblings, 0 replies; 76+ messages in thread
From: Sudeep Holla @ 2019-12-19 14:30 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Lorenzo Pieralisi, Rob Herring, linux-pm, Rafael J . Wysocki,
	Daniel Lezcano, Mark Rutland, Lina Iyer, Vincent Guittot,
	Stephen Boyd, Andy Gross, Bjorn Andersson, Kevin Hilman,
	Sudeep Holla, linux-arm-kernel, linux-arm-msm

On Wed, Dec 11, 2019 at 04:43:37PM +0100, Ulf Hansson wrote:
> Introduce a PSCI DT helper function, psci_dt_attach_cpu(), which takes a
> CPU number as an in-parameter and tries to attach the CPU's struct device
> to its corresponding PM domain.
>
> Let's makes use of dev_pm_domain_attach_by_name(), as it allows us to
> specify "psci" as the "name" of the PM domain to attach to. Additionally,
> let's also prepare the attached device to be power managed via runtime PM.
>
> Note that, the implementation of the new helper function is in a new
> separate c-file, which may seems a bit too much at this point. However,
> subsequent changes that implements the remaining part of the PM domain
> support for cpuidle-psci, helps to justify this split.
>

Reviewed-by: Sudeep Holla <sudeep.holla@arm.com>

--
Regards,
Sudeep

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 08/14] cpuidle: psci: Add a helper to attach a CPU to its PM domain
@ 2019-12-19 14:30     ` Sudeep Holla
  0 siblings, 0 replies; 76+ messages in thread
From: Sudeep Holla @ 2019-12-19 14:30 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Mark Rutland, Lorenzo Pieralisi, linux-pm, Stephen Boyd,
	linux-arm-msm, Daniel Lezcano, Rafael J . Wysocki, Andy Gross,
	Lina Iyer, Bjorn Andersson, Kevin Hilman, Rob Herring,
	Sudeep Holla, linux-arm-kernel

On Wed, Dec 11, 2019 at 04:43:37PM +0100, Ulf Hansson wrote:
> Introduce a PSCI DT helper function, psci_dt_attach_cpu(), which takes a
> CPU number as an in-parameter and tries to attach the CPU's struct device
> to its corresponding PM domain.
>
> Let's makes use of dev_pm_domain_attach_by_name(), as it allows us to
> specify "psci" as the "name" of the PM domain to attach to. Additionally,
> let's also prepare the attached device to be power managed via runtime PM.
>
> Note that, the implementation of the new helper function is in a new
> separate c-file, which may seems a bit too much at this point. However,
> subsequent changes that implements the remaining part of the PM domain
> support for cpuidle-psci, helps to justify this split.
>

Reviewed-by: Sudeep Holla <sudeep.holla@arm.com>

--
Regards,
Sudeep

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 09/14] cpuidle: psci: Attach CPU devices to their PM domains
  2019-12-11 15:43   ` Ulf Hansson
@ 2019-12-19 14:30     ` Sudeep Holla
  -1 siblings, 0 replies; 76+ messages in thread
From: Sudeep Holla @ 2019-12-19 14:30 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Lorenzo Pieralisi, Rob Herring, linux-pm, Rafael J . Wysocki,
	Daniel Lezcano, Mark Rutland, Lina Iyer, Vincent Guittot,
	Stephen Boyd, Andy Gross, Bjorn Andersson, Kevin Hilman,
	Sudeep Holla, linux-arm-kernel, linux-arm-msm

On Wed, Dec 11, 2019 at 04:43:38PM +0100, Ulf Hansson wrote:
> In order to enable a CPU to be power managed through its PM domain, let's
> try to attach it by calling psci_dt_attach_cpu() during the cpuidle
> initialization.
> 
> psci_dt_attach_cpu() returns a pointer to the attached struct device, which
> later should be used for runtime PM, hence we need to store it somewhere.
> Rather than adding yet another per CPU variable, let's create a per CPU
> struct to collect the relevant per CPU variables.
> 

Reviewed-by: Sudeep Holla <sudeep.holla@arm.com>

--
Regards,
Sudeep

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 09/14] cpuidle: psci: Attach CPU devices to their PM domains
@ 2019-12-19 14:30     ` Sudeep Holla
  0 siblings, 0 replies; 76+ messages in thread
From: Sudeep Holla @ 2019-12-19 14:30 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Mark Rutland, Lorenzo Pieralisi, linux-pm, Stephen Boyd,
	linux-arm-msm, Daniel Lezcano, Rafael J . Wysocki, Andy Gross,
	Lina Iyer, Bjorn Andersson, Kevin Hilman, Rob Herring,
	Sudeep Holla, linux-arm-kernel

On Wed, Dec 11, 2019 at 04:43:38PM +0100, Ulf Hansson wrote:
> In order to enable a CPU to be power managed through its PM domain, let's
> try to attach it by calling psci_dt_attach_cpu() during the cpuidle
> initialization.
> 
> psci_dt_attach_cpu() returns a pointer to the attached struct device, which
> later should be used for runtime PM, hence we need to store it somewhere.
> Rather than adding yet another per CPU variable, let's create a per CPU
> struct to collect the relevant per CPU variables.
> 

Reviewed-by: Sudeep Holla <sudeep.holla@arm.com>

--
Regards,
Sudeep

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 10/14] cpuidle: psci: Prepare to use OS initiated suspend mode via PM domains
  2019-12-11 15:43   ` Ulf Hansson
@ 2019-12-19 14:31     ` Sudeep Holla
  -1 siblings, 0 replies; 76+ messages in thread
From: Sudeep Holla @ 2019-12-19 14:31 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Lorenzo Pieralisi, Rob Herring, linux-pm, Rafael J . Wysocki,
	Daniel Lezcano, Mark Rutland, Lina Iyer, Vincent Guittot,
	Stephen Boyd, Andy Gross, Bjorn Andersson, Kevin Hilman,
	Sudeep Holla, linux-arm-kernel, linux-arm-msm, Lina Iyer

On Wed, Dec 11, 2019 at 04:43:39PM +0100, Ulf Hansson wrote:
> The per CPU variable psci_power_state, contains an array of fixed values,
> which reflects the corresponding arm,psci-suspend-param parsed from DT, for
> each of the available CPU idle states.
>
> This isn't sufficient when using the hierarchical CPU topology in DT, in
> combination with having PSCI OS initiated (OSI) mode enabled. More
> precisely, in OSI mode, Linux is responsible of telling the PSCI FW what
> idle state the cluster (a group of CPUs) should enter, while in PSCI
> Platform Coordinated (PC) mode, each CPU independently votes for an idle
> state of the cluster.
>
> For this reason, introduce a per CPU variable called domain_state and
> implement two helper functions to read/write its value. Then let the
> domain_state take precedence over the regular selected state, when entering
> and idle state.
>
> To avoid executing the above OSI specific code in the ->enter() callback,
> while operating in the default PSCI Platform Coordinated mode, let's also
> add a new enter-function and use it for OSI.
>
> Co-developed-by: Lina Iyer <lina.iyer@linaro.org>
> Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> ---
>
> Changes in v4:
> 	- Rebased on top of earlier changes.
> 	- Add comment about using the deepest cpuidle state for the domain state
> 	selection.
>
> ---
>  drivers/cpuidle/cpuidle-psci.c | 56 ++++++++++++++++++++++++++++++----
>  1 file changed, 50 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c
> index 6a87848be3c3..9600fe674a89 100644
> --- a/drivers/cpuidle/cpuidle-psci.c
> +++ b/drivers/cpuidle/cpuidle-psci.c
> @@ -29,14 +29,47 @@ struct psci_cpuidle_data {
>  };
>
>  static DEFINE_PER_CPU_READ_MOSTLY(struct psci_cpuidle_data, psci_cpuidle_data);
> +static DEFINE_PER_CPU(u32, domain_state);
> +

[...]

> +static int psci_enter_domain_idle_state(struct cpuidle_device *dev,
> +					struct cpuidle_driver *drv, int idx)
> +{
> +	struct psci_cpuidle_data *data = this_cpu_ptr(&psci_cpuidle_data);
> +	u32 *states = data->psci_states;

Why can't the above be like this for consistency(see below in
psci_enter_idle_state) ?

 	u32 *states = __this_cpu_read(psci_cpuidle_data.psci_states);

> +	u32 state = psci_get_domain_state();
> +	int ret;
> +
> +	if (!state)
> +		state = states[idx];
> +
> +	ret = psci_enter_state(idx, state);
> +
> +	/* Clear the domain state to start fresh when back from idle. */
> +	psci_set_domain_state(0);
> +	return ret;
> +}
>

[...]

> @@ -118,6 +152,15 @@ static int __init psci_dt_cpu_init_idle(struct device_node *cpu_node,
>  			ret = PTR_ERR(data->dev);
>  			goto free_mem;
>  		}
> +
> +		/*
> +		 * Using the deepest state for the CPU to trigger a potential
> +		 * selection of a shared state for the domain, assumes the
> +		 * domain states are all deeper states.
> +		 */
> +		if (data->dev)

You can drop this check as return on error above.

> +			drv->states[state_count - 1].enter =
> +				psci_enter_domain_idle_state;

I see the comment above but this potential blocks retention mode at
cluster level when all cpu enter retention at CPU level. I don't like
this assumption, but I don't have any better suggestion. Please add the
note that we can't enter RETENTION state at cluster/domain level when
all CPUs enter at CPU level.

As I wrote above I got another doubt. What if platform specifies just
RETENTION state at CPU as well as Cluster/domain ? I think it should be
fine, just asking it out loud.

--
Regards,
Sudeep

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 10/14] cpuidle: psci: Prepare to use OS initiated suspend mode via PM domains
@ 2019-12-19 14:31     ` Sudeep Holla
  0 siblings, 0 replies; 76+ messages in thread
From: Sudeep Holla @ 2019-12-19 14:31 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Mark Rutland, Lorenzo Pieralisi, linux-pm, Stephen Boyd,
	linux-arm-msm, Daniel Lezcano, Rafael J . Wysocki, Andy Gross,
	Lina Iyer, Bjorn Andersson, Kevin Hilman, Rob Herring, Lina Iyer,
	Sudeep Holla, linux-arm-kernel

On Wed, Dec 11, 2019 at 04:43:39PM +0100, Ulf Hansson wrote:
> The per CPU variable psci_power_state, contains an array of fixed values,
> which reflects the corresponding arm,psci-suspend-param parsed from DT, for
> each of the available CPU idle states.
>
> This isn't sufficient when using the hierarchical CPU topology in DT, in
> combination with having PSCI OS initiated (OSI) mode enabled. More
> precisely, in OSI mode, Linux is responsible of telling the PSCI FW what
> idle state the cluster (a group of CPUs) should enter, while in PSCI
> Platform Coordinated (PC) mode, each CPU independently votes for an idle
> state of the cluster.
>
> For this reason, introduce a per CPU variable called domain_state and
> implement two helper functions to read/write its value. Then let the
> domain_state take precedence over the regular selected state, when entering
> and idle state.
>
> To avoid executing the above OSI specific code in the ->enter() callback,
> while operating in the default PSCI Platform Coordinated mode, let's also
> add a new enter-function and use it for OSI.
>
> Co-developed-by: Lina Iyer <lina.iyer@linaro.org>
> Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> ---
>
> Changes in v4:
> 	- Rebased on top of earlier changes.
> 	- Add comment about using the deepest cpuidle state for the domain state
> 	selection.
>
> ---
>  drivers/cpuidle/cpuidle-psci.c | 56 ++++++++++++++++++++++++++++++----
>  1 file changed, 50 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c
> index 6a87848be3c3..9600fe674a89 100644
> --- a/drivers/cpuidle/cpuidle-psci.c
> +++ b/drivers/cpuidle/cpuidle-psci.c
> @@ -29,14 +29,47 @@ struct psci_cpuidle_data {
>  };
>
>  static DEFINE_PER_CPU_READ_MOSTLY(struct psci_cpuidle_data, psci_cpuidle_data);
> +static DEFINE_PER_CPU(u32, domain_state);
> +

[...]

> +static int psci_enter_domain_idle_state(struct cpuidle_device *dev,
> +					struct cpuidle_driver *drv, int idx)
> +{
> +	struct psci_cpuidle_data *data = this_cpu_ptr(&psci_cpuidle_data);
> +	u32 *states = data->psci_states;

Why can't the above be like this for consistency(see below in
psci_enter_idle_state) ?

 	u32 *states = __this_cpu_read(psci_cpuidle_data.psci_states);

> +	u32 state = psci_get_domain_state();
> +	int ret;
> +
> +	if (!state)
> +		state = states[idx];
> +
> +	ret = psci_enter_state(idx, state);
> +
> +	/* Clear the domain state to start fresh when back from idle. */
> +	psci_set_domain_state(0);
> +	return ret;
> +}
>

[...]

> @@ -118,6 +152,15 @@ static int __init psci_dt_cpu_init_idle(struct device_node *cpu_node,
>  			ret = PTR_ERR(data->dev);
>  			goto free_mem;
>  		}
> +
> +		/*
> +		 * Using the deepest state for the CPU to trigger a potential
> +		 * selection of a shared state for the domain, assumes the
> +		 * domain states are all deeper states.
> +		 */
> +		if (data->dev)

You can drop this check as return on error above.

> +			drv->states[state_count - 1].enter =
> +				psci_enter_domain_idle_state;

I see the comment above but this potential blocks retention mode at
cluster level when all cpu enter retention at CPU level. I don't like
this assumption, but I don't have any better suggestion. Please add the
note that we can't enter RETENTION state at cluster/domain level when
all CPUs enter at CPU level.

As I wrote above I got another doubt. What if platform specifies just
RETENTION state at CPU as well as Cluster/domain ? I think it should be
fine, just asking it out loud.

--
Regards,
Sudeep

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 11/14] cpuidle: psci: Manage runtime PM in the idle path
  2019-12-11 15:43   ` Ulf Hansson
@ 2019-12-19 14:32     ` Sudeep Holla
  -1 siblings, 0 replies; 76+ messages in thread
From: Sudeep Holla @ 2019-12-19 14:32 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Lorenzo Pieralisi, Rob Herring, linux-pm, Rafael J . Wysocki,
	Daniel Lezcano, Mark Rutland, Lina Iyer, Vincent Guittot,
	Stephen Boyd, Andy Gross, Bjorn Andersson, Kevin Hilman,
	Sudeep Holla, linux-arm-kernel, linux-arm-msm

On Wed, Dec 11, 2019 at 04:43:40PM +0100, Ulf Hansson wrote:
> In case we have succeeded to attach a CPU to its PM domain, let's deploy
> runtime PM support for the corresponding attached device, to allow the CPU
> to be powered-managed accordingly.
> 
> The triggering point for when runtime PM reference counting should be done,
> has been selected to the deepest idle state for the CPU. However, from the
> hierarchical point view, there may be good reasons to do runtime PM
> reference counting even on shallower idle states, but at this point this
> isn't supported, mainly due to limitations set by the generic PM domain.

Reviewed-by: Sudeep Holla <sudeep.holla@arm.com>

--
Regards,
Sudeep

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 11/14] cpuidle: psci: Manage runtime PM in the idle path
@ 2019-12-19 14:32     ` Sudeep Holla
  0 siblings, 0 replies; 76+ messages in thread
From: Sudeep Holla @ 2019-12-19 14:32 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Mark Rutland, Lorenzo Pieralisi, linux-pm, Stephen Boyd,
	linux-arm-msm, Daniel Lezcano, Rafael J . Wysocki, Andy Gross,
	Lina Iyer, Bjorn Andersson, Kevin Hilman, Rob Herring,
	Sudeep Holla, linux-arm-kernel

On Wed, Dec 11, 2019 at 04:43:40PM +0100, Ulf Hansson wrote:
> In case we have succeeded to attach a CPU to its PM domain, let's deploy
> runtime PM support for the corresponding attached device, to allow the CPU
> to be powered-managed accordingly.
> 
> The triggering point for when runtime PM reference counting should be done,
> has been selected to the deepest idle state for the CPU. However, from the
> hierarchical point view, there may be good reasons to do runtime PM
> reference counting even on shallower idle states, but at this point this
> isn't supported, mainly due to limitations set by the generic PM domain.

Reviewed-by: Sudeep Holla <sudeep.holla@arm.com>

--
Regards,
Sudeep

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 12/14] cpuidle: psci: Support CPU hotplug for the hierarchical model
  2019-12-11 15:43   ` Ulf Hansson
@ 2019-12-19 14:33     ` Sudeep Holla
  -1 siblings, 0 replies; 76+ messages in thread
From: Sudeep Holla @ 2019-12-19 14:33 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Lorenzo Pieralisi, Rob Herring, linux-pm, Rafael J . Wysocki,
	Daniel Lezcano, Mark Rutland, Lina Iyer, Vincent Guittot,
	Stephen Boyd, Andy Gross, Bjorn Andersson, Kevin Hilman,
	Sudeep Holla, linux-arm-kernel, linux-arm-msm

On Wed, Dec 11, 2019 at 04:43:41PM +0100, Ulf Hansson wrote:
> When the hierarchical CPU topology is used and when a CPU is put offline,
> that CPU prevents its PM domain from being powered off, which is because
> genpd observes the corresponding attached device as being active from a
> runtime PM point of view. Furthermore, any potential master PM domains are
> also prevented from being powered off.
>
> To address this limitation, let's add add a new CPU hotplug state
> (CPUHP_AP_CPU_PM_STARTING) and register up/down callbacks for it, which
> allows us to deal with runtime PM accordingly.
>
> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> ---
>
> Changes in v4:
> 	- Folded in the patch to be part of the series.
> 	- Rebased on top of earlier changes.
>
> ---
>  drivers/cpuidle/cpuidle-psci.c | 45 +++++++++++++++++++++++++++++++++-
>  include/linux/cpuhotplug.h     |  1 +
>  2 files changed, 45 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c
> index 6e7804e697ed..34a89d99bb0f 100644
> --- a/drivers/cpuidle/cpuidle-psci.c
> +++ b/drivers/cpuidle/cpuidle-psci.c
> @@ -8,6 +8,7 @@
>
>  #define pr_fmt(fmt) "CPUidle PSCI: " fmt
>
> +#include <linux/cpuhotplug.h>
>  #include <linux/cpuidle.h>
>  #include <linux/cpumask.h>
>  #include <linux/cpu_pm.h>
> @@ -31,6 +32,7 @@ struct psci_cpuidle_data {
>
>  static DEFINE_PER_CPU_READ_MOSTLY(struct psci_cpuidle_data, psci_cpuidle_data);
>  static DEFINE_PER_CPU(u32, domain_state);
> +static bool psci_cpuidle_use_cpuhp;
>

[...]

> +
> +static void psci_idle_init_cpuhp(void)
> +{

Can this be made __init along with the boolean psci_cpuidle_use_cpuhp ?

With that,
Reviewed-by: Sudeep Holla <sudeep.holla@arm.com>

--
Regards,
Sudeep

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 12/14] cpuidle: psci: Support CPU hotplug for the hierarchical model
@ 2019-12-19 14:33     ` Sudeep Holla
  0 siblings, 0 replies; 76+ messages in thread
From: Sudeep Holla @ 2019-12-19 14:33 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Mark Rutland, Lorenzo Pieralisi, linux-pm, Stephen Boyd,
	linux-arm-msm, Daniel Lezcano, Rafael J . Wysocki, Andy Gross,
	Lina Iyer, Bjorn Andersson, Kevin Hilman, Rob Herring,
	Sudeep Holla, linux-arm-kernel

On Wed, Dec 11, 2019 at 04:43:41PM +0100, Ulf Hansson wrote:
> When the hierarchical CPU topology is used and when a CPU is put offline,
> that CPU prevents its PM domain from being powered off, which is because
> genpd observes the corresponding attached device as being active from a
> runtime PM point of view. Furthermore, any potential master PM domains are
> also prevented from being powered off.
>
> To address this limitation, let's add add a new CPU hotplug state
> (CPUHP_AP_CPU_PM_STARTING) and register up/down callbacks for it, which
> allows us to deal with runtime PM accordingly.
>
> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> ---
>
> Changes in v4:
> 	- Folded in the patch to be part of the series.
> 	- Rebased on top of earlier changes.
>
> ---
>  drivers/cpuidle/cpuidle-psci.c | 45 +++++++++++++++++++++++++++++++++-
>  include/linux/cpuhotplug.h     |  1 +
>  2 files changed, 45 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c
> index 6e7804e697ed..34a89d99bb0f 100644
> --- a/drivers/cpuidle/cpuidle-psci.c
> +++ b/drivers/cpuidle/cpuidle-psci.c
> @@ -8,6 +8,7 @@
>
>  #define pr_fmt(fmt) "CPUidle PSCI: " fmt
>
> +#include <linux/cpuhotplug.h>
>  #include <linux/cpuidle.h>
>  #include <linux/cpumask.h>
>  #include <linux/cpu_pm.h>
> @@ -31,6 +32,7 @@ struct psci_cpuidle_data {
>
>  static DEFINE_PER_CPU_READ_MOSTLY(struct psci_cpuidle_data, psci_cpuidle_data);
>  static DEFINE_PER_CPU(u32, domain_state);
> +static bool psci_cpuidle_use_cpuhp;
>

[...]

> +
> +static void psci_idle_init_cpuhp(void)
> +{

Can this be made __init along with the boolean psci_cpuidle_use_cpuhp ?

With that,
Reviewed-by: Sudeep Holla <sudeep.holla@arm.com>

--
Regards,
Sudeep

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 13/14] cpuidle: psci: Add support for PM domains by using genpd
  2019-12-11 15:43   ` Ulf Hansson
@ 2019-12-19 14:34     ` Sudeep Holla
  -1 siblings, 0 replies; 76+ messages in thread
From: Sudeep Holla @ 2019-12-19 14:34 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Lorenzo Pieralisi, Rob Herring, linux-pm, Rafael J . Wysocki,
	Daniel Lezcano, Mark Rutland, Lina Iyer, Vincent Guittot,
	Stephen Boyd, Andy Gross, Bjorn Andersson, Kevin Hilman,
	Sudeep Holla, linux-arm-kernel, linux-arm-msm

On Wed, Dec 11, 2019 at 04:43:42PM +0100, Ulf Hansson wrote:
> When the hierarchical CPU topology layout is used in DT and the PSCI OSI
> mode is supported by the PSCI FW, let's initialize a corresponding PM
> domain topology by using genpd. This enables a CPU and a group of CPUs,
> when attached to the topology, to be power-managed accordingly.
>
> To trigger the attempt to initialize the genpd data structures let's use a
> subsys_initcall, which should be early enough to allow CPUs, but also other
> devices to be attached.
>
> The initialization consists of parsing the PSCI OF node for the topology
> and the "domain idle states" DT bindings. In case the idle states are
> compatible with "domain-idle-state", the initialized genpd becomes
> responsible of selecting an idle state for the PM domain, via assigning it
> a genpd governor.
>
> Note that, a successful initialization of the genpd data structures, is
> followed by a call to psci_set_osi_mode(), as to try to enable the OSI mode
> in the PSCI FW. In case this fails, we fall back into a degraded mode
> rather than bailing out and returning an error code.
>
> Co-developed-by: Lina Iyer <lina.iyer@linaro.org>
> Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> ---
>
> Changes in v4:
> 	- None.
>
> ---
>  drivers/cpuidle/cpuidle-psci-domain.c | 267 ++++++++++++++++++++++++++
>  drivers/cpuidle/cpuidle-psci.c        |   4 +-
>  drivers/cpuidle/cpuidle-psci.h        |   5 +
>  3 files changed, 274 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/cpuidle/cpuidle-psci-domain.c b/drivers/cpuidle/cpuidle-psci-domain.c
> index 656ef3d59149..c2f94ba42222 100644
> --- a/drivers/cpuidle/cpuidle-psci-domain.c
> +++ b/drivers/cpuidle/cpuidle-psci-domain.c
> @@ -7,14 +7,281 @@
>   *
>   */
>
> +#define pr_fmt(fmt) "CPUidle PSCI: " fmt
> +
>  #include <linux/cpu.h>
>  #include <linux/device.h>
>  #include <linux/kernel.h>
>  #include <linux/pm_domain.h>
>  #include <linux/pm_runtime.h>
> +#include <linux/psci.h>
> +#include <linux/slab.h>
> +#include <linux/string.h>
>
>  #include "cpuidle-psci.h"
>
> +struct psci_pd_provider {
> +	struct list_head link;
> +	struct device_node *node;
> +};
> +
> +static LIST_HEAD(psci_pd_providers);
> +static bool osi_mode_enabled;
> +
> +static int psci_pd_power_off(struct generic_pm_domain *pd)
> +{
> +	struct genpd_power_state *state = &pd->states[pd->state_idx];
> +	u32 *pd_state;
> +
> +	/* If we have failed to enable OSI mode, then abort power off. */
> +	if (!osi_mode_enabled)
> +		return -EBUSY;
> +

Why is above check needed ? Shouldn't we have disable/remove pd of
OSI is not enabled ?

> +	if (!state->data)
> +		return 0;
> +
> +	/* OSI mode is enabled, set the corresponding domain state. */
> +	pd_state = state->data;
> +	psci_set_domain_state(*pd_state);
> +
> +	return 0;
> +}
> +

[...]

> +static const struct of_device_id psci_of_match[] __initconst = {
> +	{ .compatible = "arm,psci" },

I think we can drop the above one as it's for v0.1 which didn't support
OSI.

> +	{ .compatible = "arm,psci-0.2" },
> +	{ .compatible = "arm,psci-1.0" },
> +	{}
> +};
> +
> +static int __init psci_idle_init_domains(void)
> +{
> +	struct device_node *np = of_find_matching_node(NULL, psci_of_match);
> +	struct device_node *node;
> +	int ret = 0, pd_count = 0;
> +
> +	if (!np)
> +		return -ENODEV;
> +
> +	/* Currently limit the hierarchical topology to be used in OSI mode. */
> +	if (!psci_has_osi_support())
> +		goto out;
> +
> +	/*
> +	 * Parse child nodes for the "#power-domain-cells" property and
> +	 * initialize a genpd/genpd-of-provider pair when it's found.
> +	 */
> +	for_each_child_of_node(np, node) {
> +		if (!of_find_property(node, "#power-domain-cells", NULL))
> +			continue;
> +
> +		ret = psci_pd_init(node);
> +		if (ret)
> +			goto put_node;
> +
> +		pd_count++;
> +	}
> +
> +	/* Bail out if not using the hierarchical CPU topology. */
> +	if (!pd_count)
> +		goto out;
> +
> +	/* Link genpd masters/subdomains to model the CPU topology. */
> +	ret = psci_pd_init_topology(np);
> +	if (ret)
> +		goto remove_pd;
> +
> +	/* Try to enable OSI mode. */
> +	ret = psci_set_osi_mode();
> +	if (ret)
> +		pr_warn("failed to enable OSI mode: %d\n", ret);

Same question as above: shouldn't we disable and goto remove_pd ?

--
Regards,
Sudeep

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 13/14] cpuidle: psci: Add support for PM domains by using genpd
@ 2019-12-19 14:34     ` Sudeep Holla
  0 siblings, 0 replies; 76+ messages in thread
From: Sudeep Holla @ 2019-12-19 14:34 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Mark Rutland, Lorenzo Pieralisi, linux-pm, Stephen Boyd,
	linux-arm-msm, Daniel Lezcano, Rafael J . Wysocki, Andy Gross,
	Lina Iyer, Bjorn Andersson, Kevin Hilman, Rob Herring,
	Sudeep Holla, linux-arm-kernel

On Wed, Dec 11, 2019 at 04:43:42PM +0100, Ulf Hansson wrote:
> When the hierarchical CPU topology layout is used in DT and the PSCI OSI
> mode is supported by the PSCI FW, let's initialize a corresponding PM
> domain topology by using genpd. This enables a CPU and a group of CPUs,
> when attached to the topology, to be power-managed accordingly.
>
> To trigger the attempt to initialize the genpd data structures let's use a
> subsys_initcall, which should be early enough to allow CPUs, but also other
> devices to be attached.
>
> The initialization consists of parsing the PSCI OF node for the topology
> and the "domain idle states" DT bindings. In case the idle states are
> compatible with "domain-idle-state", the initialized genpd becomes
> responsible of selecting an idle state for the PM domain, via assigning it
> a genpd governor.
>
> Note that, a successful initialization of the genpd data structures, is
> followed by a call to psci_set_osi_mode(), as to try to enable the OSI mode
> in the PSCI FW. In case this fails, we fall back into a degraded mode
> rather than bailing out and returning an error code.
>
> Co-developed-by: Lina Iyer <lina.iyer@linaro.org>
> Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> ---
>
> Changes in v4:
> 	- None.
>
> ---
>  drivers/cpuidle/cpuidle-psci-domain.c | 267 ++++++++++++++++++++++++++
>  drivers/cpuidle/cpuidle-psci.c        |   4 +-
>  drivers/cpuidle/cpuidle-psci.h        |   5 +
>  3 files changed, 274 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/cpuidle/cpuidle-psci-domain.c b/drivers/cpuidle/cpuidle-psci-domain.c
> index 656ef3d59149..c2f94ba42222 100644
> --- a/drivers/cpuidle/cpuidle-psci-domain.c
> +++ b/drivers/cpuidle/cpuidle-psci-domain.c
> @@ -7,14 +7,281 @@
>   *
>   */
>
> +#define pr_fmt(fmt) "CPUidle PSCI: " fmt
> +
>  #include <linux/cpu.h>
>  #include <linux/device.h>
>  #include <linux/kernel.h>
>  #include <linux/pm_domain.h>
>  #include <linux/pm_runtime.h>
> +#include <linux/psci.h>
> +#include <linux/slab.h>
> +#include <linux/string.h>
>
>  #include "cpuidle-psci.h"
>
> +struct psci_pd_provider {
> +	struct list_head link;
> +	struct device_node *node;
> +};
> +
> +static LIST_HEAD(psci_pd_providers);
> +static bool osi_mode_enabled;
> +
> +static int psci_pd_power_off(struct generic_pm_domain *pd)
> +{
> +	struct genpd_power_state *state = &pd->states[pd->state_idx];
> +	u32 *pd_state;
> +
> +	/* If we have failed to enable OSI mode, then abort power off. */
> +	if (!osi_mode_enabled)
> +		return -EBUSY;
> +

Why is above check needed ? Shouldn't we have disable/remove pd of
OSI is not enabled ?

> +	if (!state->data)
> +		return 0;
> +
> +	/* OSI mode is enabled, set the corresponding domain state. */
> +	pd_state = state->data;
> +	psci_set_domain_state(*pd_state);
> +
> +	return 0;
> +}
> +

[...]

> +static const struct of_device_id psci_of_match[] __initconst = {
> +	{ .compatible = "arm,psci" },

I think we can drop the above one as it's for v0.1 which didn't support
OSI.

> +	{ .compatible = "arm,psci-0.2" },
> +	{ .compatible = "arm,psci-1.0" },
> +	{}
> +};
> +
> +static int __init psci_idle_init_domains(void)
> +{
> +	struct device_node *np = of_find_matching_node(NULL, psci_of_match);
> +	struct device_node *node;
> +	int ret = 0, pd_count = 0;
> +
> +	if (!np)
> +		return -ENODEV;
> +
> +	/* Currently limit the hierarchical topology to be used in OSI mode. */
> +	if (!psci_has_osi_support())
> +		goto out;
> +
> +	/*
> +	 * Parse child nodes for the "#power-domain-cells" property and
> +	 * initialize a genpd/genpd-of-provider pair when it's found.
> +	 */
> +	for_each_child_of_node(np, node) {
> +		if (!of_find_property(node, "#power-domain-cells", NULL))
> +			continue;
> +
> +		ret = psci_pd_init(node);
> +		if (ret)
> +			goto put_node;
> +
> +		pd_count++;
> +	}
> +
> +	/* Bail out if not using the hierarchical CPU topology. */
> +	if (!pd_count)
> +		goto out;
> +
> +	/* Link genpd masters/subdomains to model the CPU topology. */
> +	ret = psci_pd_init_topology(np);
> +	if (ret)
> +		goto remove_pd;
> +
> +	/* Try to enable OSI mode. */
> +	ret = psci_set_osi_mode();
> +	if (ret)
> +		pr_warn("failed to enable OSI mode: %d\n", ret);

Same question as above: shouldn't we disable and goto remove_pd ?

--
Regards,
Sudeep

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 14/14] arm64: dts: Convert to the hierarchical CPU topology layout for MSM8916
  2019-12-11 15:43   ` Ulf Hansson
@ 2019-12-19 14:34     ` Sudeep Holla
  -1 siblings, 0 replies; 76+ messages in thread
From: Sudeep Holla @ 2019-12-19 14:34 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Lorenzo Pieralisi, Rob Herring, linux-pm, Rafael J . Wysocki,
	Daniel Lezcano, Mark Rutland, Lina Iyer, Vincent Guittot,
	Stephen Boyd, Andy Gross, Bjorn Andersson, Kevin Hilman,
	Sudeep Holla, linux-arm-kernel, linux-arm-msm

On Wed, Dec 11, 2019 at 04:43:43PM +0100, Ulf Hansson wrote:
> To enable the OS to better support PSCI OS initiated CPU suspend mode,
> let's convert from the flattened layout to the hierarchical layout.
>
> In the hierarchical layout, let's create a power domain provider per CPU
> and describe the idle states for each CPU inside the power domain provider
> node. To group the CPUs into a cluster, let's add another power domain
> provider and make it act as the master domain. Note that, the CPU's idle
> states remains compatible with "arm,idle-state", while the cluster's idle
> state becomes compatible with "domain-idle-state".
>
> Co-developed-by: Lina Iyer <lina.iyer@linaro.org>
> Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> ---
>
> Changes in v4:
> 	- None.
>
> ---
>  arch/arm64/boot/dts/qcom/msm8916.dtsi | 57 +++++++++++++++++++++++++--
>  1 file changed, 53 insertions(+), 4 deletions(-)
>
> diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> index 8686e101905c..282c36c8fa3b 100644
> --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
> +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> @@ -102,10 +102,11 @@
>  			reg = <0x0>;
>  			next-level-cache = <&L2_0>;
>  			enable-method = "psci";
> -			cpu-idle-states = <&CPU_SLEEP_0>;
>  			clocks = <&apcs>;
>  			operating-points-v2 = <&cpu_opp_table>;
>  			#cooling-cells = <2>;
> +			power-domains = <&CPU_PD0>;
> +			power-domain-names = "psci";
>  		};
>
>  		CPU1: cpu@1 {
> @@ -114,10 +115,11 @@
>  			reg = <0x1>;
>  			next-level-cache = <&L2_0>;
>  			enable-method = "psci";
> -			cpu-idle-states = <&CPU_SLEEP_0>;
>  			clocks = <&apcs>;
>  			operating-points-v2 = <&cpu_opp_table>;
>  			#cooling-cells = <2>;
> +			power-domains = <&CPU_PD1>;
> +			power-domain-names = "psci";
>  		};
>
>  		CPU2: cpu@2 {
> @@ -126,10 +128,11 @@
>  			reg = <0x2>;
>  			next-level-cache = <&L2_0>;
>  			enable-method = "psci";
> -			cpu-idle-states = <&CPU_SLEEP_0>;
>  			clocks = <&apcs>;
>  			operating-points-v2 = <&cpu_opp_table>;
>  			#cooling-cells = <2>;
> +			power-domains = <&CPU_PD2>;
> +			power-domain-names = "psci";
>  		};
>
>  		CPU3: cpu@3 {
> @@ -138,10 +141,11 @@
>  			reg = <0x3>;
>  			next-level-cache = <&L2_0>;
>  			enable-method = "psci";
> -			cpu-idle-states = <&CPU_SLEEP_0>;
>  			clocks = <&apcs>;
>  			operating-points-v2 = <&cpu_opp_table>;
>  			#cooling-cells = <2>;
> +			power-domains = <&CPU_PD3>;
> +			power-domain-names = "psci";
>  		};
>
>  		L2_0: l2-cache {
> @@ -161,12 +165,57 @@
>  				min-residency-us = <2000>;
>  				local-timer-stop;
>  			};
> +
> +			CLUSTER_RET: cluster-retention {
> +				compatible = "domain-idle-state";
> +				arm,psci-suspend-param = <0x41000012>;

If I followed the thread correctly, we are now just using the param as is
without any extra logic like ORing like before. i.e. The domain state
parameter overrides the any param below it in the hierarchy.

If that's correct, then
Acked-by: Sudeep Holla <sudeep.holla@arm.com>

--
Regards,
Sudeep

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 14/14] arm64: dts: Convert to the hierarchical CPU topology layout for MSM8916
@ 2019-12-19 14:34     ` Sudeep Holla
  0 siblings, 0 replies; 76+ messages in thread
From: Sudeep Holla @ 2019-12-19 14:34 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Mark Rutland, Lorenzo Pieralisi, linux-pm, Stephen Boyd,
	linux-arm-msm, Daniel Lezcano, Rafael J . Wysocki, Andy Gross,
	Lina Iyer, Bjorn Andersson, Kevin Hilman, Rob Herring,
	Sudeep Holla, linux-arm-kernel

On Wed, Dec 11, 2019 at 04:43:43PM +0100, Ulf Hansson wrote:
> To enable the OS to better support PSCI OS initiated CPU suspend mode,
> let's convert from the flattened layout to the hierarchical layout.
>
> In the hierarchical layout, let's create a power domain provider per CPU
> and describe the idle states for each CPU inside the power domain provider
> node. To group the CPUs into a cluster, let's add another power domain
> provider and make it act as the master domain. Note that, the CPU's idle
> states remains compatible with "arm,idle-state", while the cluster's idle
> state becomes compatible with "domain-idle-state".
>
> Co-developed-by: Lina Iyer <lina.iyer@linaro.org>
> Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> ---
>
> Changes in v4:
> 	- None.
>
> ---
>  arch/arm64/boot/dts/qcom/msm8916.dtsi | 57 +++++++++++++++++++++++++--
>  1 file changed, 53 insertions(+), 4 deletions(-)
>
> diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> index 8686e101905c..282c36c8fa3b 100644
> --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
> +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> @@ -102,10 +102,11 @@
>  			reg = <0x0>;
>  			next-level-cache = <&L2_0>;
>  			enable-method = "psci";
> -			cpu-idle-states = <&CPU_SLEEP_0>;
>  			clocks = <&apcs>;
>  			operating-points-v2 = <&cpu_opp_table>;
>  			#cooling-cells = <2>;
> +			power-domains = <&CPU_PD0>;
> +			power-domain-names = "psci";
>  		};
>
>  		CPU1: cpu@1 {
> @@ -114,10 +115,11 @@
>  			reg = <0x1>;
>  			next-level-cache = <&L2_0>;
>  			enable-method = "psci";
> -			cpu-idle-states = <&CPU_SLEEP_0>;
>  			clocks = <&apcs>;
>  			operating-points-v2 = <&cpu_opp_table>;
>  			#cooling-cells = <2>;
> +			power-domains = <&CPU_PD1>;
> +			power-domain-names = "psci";
>  		};
>
>  		CPU2: cpu@2 {
> @@ -126,10 +128,11 @@
>  			reg = <0x2>;
>  			next-level-cache = <&L2_0>;
>  			enable-method = "psci";
> -			cpu-idle-states = <&CPU_SLEEP_0>;
>  			clocks = <&apcs>;
>  			operating-points-v2 = <&cpu_opp_table>;
>  			#cooling-cells = <2>;
> +			power-domains = <&CPU_PD2>;
> +			power-domain-names = "psci";
>  		};
>
>  		CPU3: cpu@3 {
> @@ -138,10 +141,11 @@
>  			reg = <0x3>;
>  			next-level-cache = <&L2_0>;
>  			enable-method = "psci";
> -			cpu-idle-states = <&CPU_SLEEP_0>;
>  			clocks = <&apcs>;
>  			operating-points-v2 = <&cpu_opp_table>;
>  			#cooling-cells = <2>;
> +			power-domains = <&CPU_PD3>;
> +			power-domain-names = "psci";
>  		};
>
>  		L2_0: l2-cache {
> @@ -161,12 +165,57 @@
>  				min-residency-us = <2000>;
>  				local-timer-stop;
>  			};
> +
> +			CLUSTER_RET: cluster-retention {
> +				compatible = "domain-idle-state";
> +				arm,psci-suspend-param = <0x41000012>;

If I followed the thread correctly, we are now just using the param as is
without any extra logic like ORing like before. i.e. The domain state
parameter overrides the any param below it in the hierarchy.

If that's correct, then
Acked-by: Sudeep Holla <sudeep.holla@arm.com>

--
Regards,
Sudeep

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 10/14] cpuidle: psci: Prepare to use OS initiated suspend mode via PM domains
  2019-12-19 14:31     ` Sudeep Holla
@ 2019-12-19 15:48       ` Ulf Hansson
  -1 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-19 15:48 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: Lorenzo Pieralisi, Rob Herring, Linux PM, Rafael J . Wysocki,
	Daniel Lezcano, Mark Rutland, Lina Iyer, Vincent Guittot,
	Stephen Boyd, Andy Gross, Bjorn Andersson, Kevin Hilman,
	Linux ARM, linux-arm-msm, Lina Iyer

On Thu, 19 Dec 2019 at 15:32, Sudeep Holla <sudeep.holla@arm.com> wrote:
>
> On Wed, Dec 11, 2019 at 04:43:39PM +0100, Ulf Hansson wrote:
> > The per CPU variable psci_power_state, contains an array of fixed values,
> > which reflects the corresponding arm,psci-suspend-param parsed from DT, for
> > each of the available CPU idle states.
> >
> > This isn't sufficient when using the hierarchical CPU topology in DT, in
> > combination with having PSCI OS initiated (OSI) mode enabled. More
> > precisely, in OSI mode, Linux is responsible of telling the PSCI FW what
> > idle state the cluster (a group of CPUs) should enter, while in PSCI
> > Platform Coordinated (PC) mode, each CPU independently votes for an idle
> > state of the cluster.
> >
> > For this reason, introduce a per CPU variable called domain_state and
> > implement two helper functions to read/write its value. Then let the
> > domain_state take precedence over the regular selected state, when entering
> > and idle state.
> >
> > To avoid executing the above OSI specific code in the ->enter() callback,
> > while operating in the default PSCI Platform Coordinated mode, let's also
> > add a new enter-function and use it for OSI.
> >
> > Co-developed-by: Lina Iyer <lina.iyer@linaro.org>
> > Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
> > Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> > ---
> >
> > Changes in v4:
> >       - Rebased on top of earlier changes.
> >       - Add comment about using the deepest cpuidle state for the domain state
> >       selection.
> >
> > ---
> >  drivers/cpuidle/cpuidle-psci.c | 56 ++++++++++++++++++++++++++++++----
> >  1 file changed, 50 insertions(+), 6 deletions(-)
> >
> > diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c
> > index 6a87848be3c3..9600fe674a89 100644
> > --- a/drivers/cpuidle/cpuidle-psci.c
> > +++ b/drivers/cpuidle/cpuidle-psci.c
> > @@ -29,14 +29,47 @@ struct psci_cpuidle_data {
> >  };
> >
> >  static DEFINE_PER_CPU_READ_MOSTLY(struct psci_cpuidle_data, psci_cpuidle_data);
> > +static DEFINE_PER_CPU(u32, domain_state);
> > +
>
> [...]
>
> > +static int psci_enter_domain_idle_state(struct cpuidle_device *dev,
> > +                                     struct cpuidle_driver *drv, int idx)
> > +{
> > +     struct psci_cpuidle_data *data = this_cpu_ptr(&psci_cpuidle_data);
> > +     u32 *states = data->psci_states;
>
> Why can't the above be like this for consistency(see below in
> psci_enter_idle_state) ?

You have a point, however in patch11 I am adding this line below.

struct device *pd_dev = data->dev;

So I don't think it matters much, agree?

>
>         u32 *states = __this_cpu_read(psci_cpuidle_data.psci_states);
>
> > +     u32 state = psci_get_domain_state();
> > +     int ret;
> > +
> > +     if (!state)
> > +             state = states[idx];
> > +
> > +     ret = psci_enter_state(idx, state);
> > +
> > +     /* Clear the domain state to start fresh when back from idle. */
> > +     psci_set_domain_state(0);
> > +     return ret;
> > +}
> >
>
> [...]
>
> > @@ -118,6 +152,15 @@ static int __init psci_dt_cpu_init_idle(struct device_node *cpu_node,
> >                       ret = PTR_ERR(data->dev);
> >                       goto free_mem;
> >               }
> > +
> > +             /*
> > +              * Using the deepest state for the CPU to trigger a potential
> > +              * selection of a shared state for the domain, assumes the
> > +              * domain states are all deeper states.
> > +              */
> > +             if (data->dev)
>
> You can drop this check as return on error above.

Actually not, because if OSI is supported, there is still a
possibility that the PM domain topology isn't used.

This means ->data->dev is NULL.

>
> > +                     drv->states[state_count - 1].enter =
> > +                             psci_enter_domain_idle_state;
>
> I see the comment above but this potential blocks retention mode at
> cluster level when all cpu enter retention at CPU level. I don't like
> this assumption, but I don't have any better suggestion. Please add the
> note that we can't enter RETENTION state at cluster/domain level when
> all CPUs enter at CPU level.

You are correct, but I think the comment a few lines above (agreed to
be added by Lorenzo in the previous version) should be enough to
explain that. No?

The point is, this is only a problem if cluster RETENTION is
considered to be a shallower state that CPU power off, for example.

>
> As I wrote above I got another doubt. What if platform specifies just
> RETENTION state at CPU as well as Cluster/domain ? I think it should be
> fine, just asking it out loud.

It's fine.

However, I am looking at what future improvements that can be made.
This is one of them, but let's discuss that later on.

Kind regards
Uffe

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 10/14] cpuidle: psci: Prepare to use OS initiated suspend mode via PM domains
@ 2019-12-19 15:48       ` Ulf Hansson
  0 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-19 15:48 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: Mark Rutland, Lorenzo Pieralisi, Linux PM, Stephen Boyd,
	linux-arm-msm, Daniel Lezcano, Rafael J . Wysocki, Andy Gross,
	Lina Iyer, Bjorn Andersson, Kevin Hilman, Rob Herring, Lina Iyer,
	Linux ARM

On Thu, 19 Dec 2019 at 15:32, Sudeep Holla <sudeep.holla@arm.com> wrote:
>
> On Wed, Dec 11, 2019 at 04:43:39PM +0100, Ulf Hansson wrote:
> > The per CPU variable psci_power_state, contains an array of fixed values,
> > which reflects the corresponding arm,psci-suspend-param parsed from DT, for
> > each of the available CPU idle states.
> >
> > This isn't sufficient when using the hierarchical CPU topology in DT, in
> > combination with having PSCI OS initiated (OSI) mode enabled. More
> > precisely, in OSI mode, Linux is responsible of telling the PSCI FW what
> > idle state the cluster (a group of CPUs) should enter, while in PSCI
> > Platform Coordinated (PC) mode, each CPU independently votes for an idle
> > state of the cluster.
> >
> > For this reason, introduce a per CPU variable called domain_state and
> > implement two helper functions to read/write its value. Then let the
> > domain_state take precedence over the regular selected state, when entering
> > and idle state.
> >
> > To avoid executing the above OSI specific code in the ->enter() callback,
> > while operating in the default PSCI Platform Coordinated mode, let's also
> > add a new enter-function and use it for OSI.
> >
> > Co-developed-by: Lina Iyer <lina.iyer@linaro.org>
> > Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
> > Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> > ---
> >
> > Changes in v4:
> >       - Rebased on top of earlier changes.
> >       - Add comment about using the deepest cpuidle state for the domain state
> >       selection.
> >
> > ---
> >  drivers/cpuidle/cpuidle-psci.c | 56 ++++++++++++++++++++++++++++++----
> >  1 file changed, 50 insertions(+), 6 deletions(-)
> >
> > diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c
> > index 6a87848be3c3..9600fe674a89 100644
> > --- a/drivers/cpuidle/cpuidle-psci.c
> > +++ b/drivers/cpuidle/cpuidle-psci.c
> > @@ -29,14 +29,47 @@ struct psci_cpuidle_data {
> >  };
> >
> >  static DEFINE_PER_CPU_READ_MOSTLY(struct psci_cpuidle_data, psci_cpuidle_data);
> > +static DEFINE_PER_CPU(u32, domain_state);
> > +
>
> [...]
>
> > +static int psci_enter_domain_idle_state(struct cpuidle_device *dev,
> > +                                     struct cpuidle_driver *drv, int idx)
> > +{
> > +     struct psci_cpuidle_data *data = this_cpu_ptr(&psci_cpuidle_data);
> > +     u32 *states = data->psci_states;
>
> Why can't the above be like this for consistency(see below in
> psci_enter_idle_state) ?

You have a point, however in patch11 I am adding this line below.

struct device *pd_dev = data->dev;

So I don't think it matters much, agree?

>
>         u32 *states = __this_cpu_read(psci_cpuidle_data.psci_states);
>
> > +     u32 state = psci_get_domain_state();
> > +     int ret;
> > +
> > +     if (!state)
> > +             state = states[idx];
> > +
> > +     ret = psci_enter_state(idx, state);
> > +
> > +     /* Clear the domain state to start fresh when back from idle. */
> > +     psci_set_domain_state(0);
> > +     return ret;
> > +}
> >
>
> [...]
>
> > @@ -118,6 +152,15 @@ static int __init psci_dt_cpu_init_idle(struct device_node *cpu_node,
> >                       ret = PTR_ERR(data->dev);
> >                       goto free_mem;
> >               }
> > +
> > +             /*
> > +              * Using the deepest state for the CPU to trigger a potential
> > +              * selection of a shared state for the domain, assumes the
> > +              * domain states are all deeper states.
> > +              */
> > +             if (data->dev)
>
> You can drop this check as return on error above.

Actually not, because if OSI is supported, there is still a
possibility that the PM domain topology isn't used.

This means ->data->dev is NULL.

>
> > +                     drv->states[state_count - 1].enter =
> > +                             psci_enter_domain_idle_state;
>
> I see the comment above but this potential blocks retention mode at
> cluster level when all cpu enter retention at CPU level. I don't like
> this assumption, but I don't have any better suggestion. Please add the
> note that we can't enter RETENTION state at cluster/domain level when
> all CPUs enter at CPU level.

You are correct, but I think the comment a few lines above (agreed to
be added by Lorenzo in the previous version) should be enough to
explain that. No?

The point is, this is only a problem if cluster RETENTION is
considered to be a shallower state that CPU power off, for example.

>
> As I wrote above I got another doubt. What if platform specifies just
> RETENTION state at CPU as well as Cluster/domain ? I think it should be
> fine, just asking it out loud.

It's fine.

However, I am looking at what future improvements that can be made.
This is one of them, but let's discuss that later on.

Kind regards
Uffe

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 12/14] cpuidle: psci: Support CPU hotplug for the hierarchical model
  2019-12-19 14:33     ` Sudeep Holla
@ 2019-12-19 15:48       ` Ulf Hansson
  -1 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-19 15:48 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: Lorenzo Pieralisi, Rob Herring, Linux PM, Rafael J . Wysocki,
	Daniel Lezcano, Mark Rutland, Lina Iyer, Vincent Guittot,
	Stephen Boyd, Andy Gross, Bjorn Andersson, Kevin Hilman,
	Linux ARM, linux-arm-msm

On Thu, 19 Dec 2019 at 15:33, Sudeep Holla <sudeep.holla@arm.com> wrote:
>
> On Wed, Dec 11, 2019 at 04:43:41PM +0100, Ulf Hansson wrote:
> > When the hierarchical CPU topology is used and when a CPU is put offline,
> > that CPU prevents its PM domain from being powered off, which is because
> > genpd observes the corresponding attached device as being active from a
> > runtime PM point of view. Furthermore, any potential master PM domains are
> > also prevented from being powered off.
> >
> > To address this limitation, let's add add a new CPU hotplug state
> > (CPUHP_AP_CPU_PM_STARTING) and register up/down callbacks for it, which
> > allows us to deal with runtime PM accordingly.
> >
> > Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> > ---
> >
> > Changes in v4:
> >       - Folded in the patch to be part of the series.
> >       - Rebased on top of earlier changes.
> >
> > ---
> >  drivers/cpuidle/cpuidle-psci.c | 45 +++++++++++++++++++++++++++++++++-
> >  include/linux/cpuhotplug.h     |  1 +
> >  2 files changed, 45 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c
> > index 6e7804e697ed..34a89d99bb0f 100644
> > --- a/drivers/cpuidle/cpuidle-psci.c
> > +++ b/drivers/cpuidle/cpuidle-psci.c
> > @@ -8,6 +8,7 @@
> >
> >  #define pr_fmt(fmt) "CPUidle PSCI: " fmt
> >
> > +#include <linux/cpuhotplug.h>
> >  #include <linux/cpuidle.h>
> >  #include <linux/cpumask.h>
> >  #include <linux/cpu_pm.h>
> > @@ -31,6 +32,7 @@ struct psci_cpuidle_data {
> >
> >  static DEFINE_PER_CPU_READ_MOSTLY(struct psci_cpuidle_data, psci_cpuidle_data);
> >  static DEFINE_PER_CPU(u32, domain_state);
> > +static bool psci_cpuidle_use_cpuhp;
> >
>
> [...]
>
> > +
> > +static void psci_idle_init_cpuhp(void)
> > +{
>
> Can this be made __init along with the boolean psci_cpuidle_use_cpuhp ?

Yeah, make sense!

>
> With that,
> Reviewed-by: Sudeep Holla <sudeep.holla@arm.com>

Thanks!

Kind regards
Uffe

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 12/14] cpuidle: psci: Support CPU hotplug for the hierarchical model
@ 2019-12-19 15:48       ` Ulf Hansson
  0 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-19 15:48 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: Mark Rutland, Lorenzo Pieralisi, Linux PM, Stephen Boyd,
	linux-arm-msm, Daniel Lezcano, Rafael J . Wysocki, Andy Gross,
	Lina Iyer, Bjorn Andersson, Kevin Hilman, Rob Herring, Linux ARM

On Thu, 19 Dec 2019 at 15:33, Sudeep Holla <sudeep.holla@arm.com> wrote:
>
> On Wed, Dec 11, 2019 at 04:43:41PM +0100, Ulf Hansson wrote:
> > When the hierarchical CPU topology is used and when a CPU is put offline,
> > that CPU prevents its PM domain from being powered off, which is because
> > genpd observes the corresponding attached device as being active from a
> > runtime PM point of view. Furthermore, any potential master PM domains are
> > also prevented from being powered off.
> >
> > To address this limitation, let's add add a new CPU hotplug state
> > (CPUHP_AP_CPU_PM_STARTING) and register up/down callbacks for it, which
> > allows us to deal with runtime PM accordingly.
> >
> > Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> > ---
> >
> > Changes in v4:
> >       - Folded in the patch to be part of the series.
> >       - Rebased on top of earlier changes.
> >
> > ---
> >  drivers/cpuidle/cpuidle-psci.c | 45 +++++++++++++++++++++++++++++++++-
> >  include/linux/cpuhotplug.h     |  1 +
> >  2 files changed, 45 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c
> > index 6e7804e697ed..34a89d99bb0f 100644
> > --- a/drivers/cpuidle/cpuidle-psci.c
> > +++ b/drivers/cpuidle/cpuidle-psci.c
> > @@ -8,6 +8,7 @@
> >
> >  #define pr_fmt(fmt) "CPUidle PSCI: " fmt
> >
> > +#include <linux/cpuhotplug.h>
> >  #include <linux/cpuidle.h>
> >  #include <linux/cpumask.h>
> >  #include <linux/cpu_pm.h>
> > @@ -31,6 +32,7 @@ struct psci_cpuidle_data {
> >
> >  static DEFINE_PER_CPU_READ_MOSTLY(struct psci_cpuidle_data, psci_cpuidle_data);
> >  static DEFINE_PER_CPU(u32, domain_state);
> > +static bool psci_cpuidle_use_cpuhp;
> >
>
> [...]
>
> > +
> > +static void psci_idle_init_cpuhp(void)
> > +{
>
> Can this be made __init along with the boolean psci_cpuidle_use_cpuhp ?

Yeah, make sense!

>
> With that,
> Reviewed-by: Sudeep Holla <sudeep.holla@arm.com>

Thanks!

Kind regards
Uffe

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 13/14] cpuidle: psci: Add support for PM domains by using genpd
  2019-12-19 14:34     ` Sudeep Holla
@ 2019-12-19 15:48       ` Ulf Hansson
  -1 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-19 15:48 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: Lorenzo Pieralisi, Rob Herring, Linux PM, Rafael J . Wysocki,
	Daniel Lezcano, Mark Rutland, Lina Iyer, Vincent Guittot,
	Stephen Boyd, Andy Gross, Bjorn Andersson, Kevin Hilman,
	Linux ARM, linux-arm-msm

On Thu, 19 Dec 2019 at 15:34, Sudeep Holla <sudeep.holla@arm.com> wrote:
>
> On Wed, Dec 11, 2019 at 04:43:42PM +0100, Ulf Hansson wrote:
> > When the hierarchical CPU topology layout is used in DT and the PSCI OSI
> > mode is supported by the PSCI FW, let's initialize a corresponding PM
> > domain topology by using genpd. This enables a CPU and a group of CPUs,
> > when attached to the topology, to be power-managed accordingly.
> >
> > To trigger the attempt to initialize the genpd data structures let's use a
> > subsys_initcall, which should be early enough to allow CPUs, but also other
> > devices to be attached.
> >
> > The initialization consists of parsing the PSCI OF node for the topology
> > and the "domain idle states" DT bindings. In case the idle states are
> > compatible with "domain-idle-state", the initialized genpd becomes
> > responsible of selecting an idle state for the PM domain, via assigning it
> > a genpd governor.
> >
> > Note that, a successful initialization of the genpd data structures, is
> > followed by a call to psci_set_osi_mode(), as to try to enable the OSI mode
> > in the PSCI FW. In case this fails, we fall back into a degraded mode
> > rather than bailing out and returning an error code.
> >
> > Co-developed-by: Lina Iyer <lina.iyer@linaro.org>
> > Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
> > Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> > ---
> >
> > Changes in v4:
> >       - None.
> >
> > ---
> >  drivers/cpuidle/cpuidle-psci-domain.c | 267 ++++++++++++++++++++++++++
> >  drivers/cpuidle/cpuidle-psci.c        |   4 +-
> >  drivers/cpuidle/cpuidle-psci.h        |   5 +
> >  3 files changed, 274 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/cpuidle/cpuidle-psci-domain.c b/drivers/cpuidle/cpuidle-psci-domain.c
> > index 656ef3d59149..c2f94ba42222 100644
> > --- a/drivers/cpuidle/cpuidle-psci-domain.c
> > +++ b/drivers/cpuidle/cpuidle-psci-domain.c
> > @@ -7,14 +7,281 @@
> >   *
> >   */
> >
> > +#define pr_fmt(fmt) "CPUidle PSCI: " fmt
> > +
> >  #include <linux/cpu.h>
> >  #include <linux/device.h>
> >  #include <linux/kernel.h>
> >  #include <linux/pm_domain.h>
> >  #include <linux/pm_runtime.h>
> > +#include <linux/psci.h>
> > +#include <linux/slab.h>
> > +#include <linux/string.h>
> >
> >  #include "cpuidle-psci.h"
> >
> > +struct psci_pd_provider {
> > +     struct list_head link;
> > +     struct device_node *node;
> > +};
> > +
> > +static LIST_HEAD(psci_pd_providers);
> > +static bool osi_mode_enabled;
> > +
> > +static int psci_pd_power_off(struct generic_pm_domain *pd)
> > +{
> > +     struct genpd_power_state *state = &pd->states[pd->state_idx];
> > +     u32 *pd_state;
> > +
> > +     /* If we have failed to enable OSI mode, then abort power off. */
> > +     if (!osi_mode_enabled)
> > +             return -EBUSY;
> > +
>
> Why is above check needed ? Shouldn't we have disable/remove pd of
> OSI is not enabled ?

Well, failing to enable OSI should in practice not happen, while it
theoretically it could.

My approach to this has been to fall back to use a "degraded mode",
which seems quite common for these kind of situations. The degraded
mode means, we are preventing domain states from being used.

More importantly, it also keeps the code registering the PM domains, a
bit simpler.

>
> > +     if (!state->data)
> > +             return 0;
> > +
> > +     /* OSI mode is enabled, set the corresponding domain state. */
> > +     pd_state = state->data;
> > +     psci_set_domain_state(*pd_state);
> > +
> > +     return 0;
> > +}
> > +
>
> [...]
>
> > +static const struct of_device_id psci_of_match[] __initconst = {
> > +     { .compatible = "arm,psci" },
>
> I think we can drop the above one as it's for v0.1 which didn't support
> OSI.

Yeah, I do that.

>
> > +     { .compatible = "arm,psci-0.2" },
> > +     { .compatible = "arm,psci-1.0" },
> > +     {}
> > +};
> > +
> > +static int __init psci_idle_init_domains(void)
> > +{
> > +     struct device_node *np = of_find_matching_node(NULL, psci_of_match);
> > +     struct device_node *node;
> > +     int ret = 0, pd_count = 0;
> > +
> > +     if (!np)
> > +             return -ENODEV;
> > +
> > +     /* Currently limit the hierarchical topology to be used in OSI mode. */
> > +     if (!psci_has_osi_support())
> > +             goto out;
> > +
> > +     /*
> > +      * Parse child nodes for the "#power-domain-cells" property and
> > +      * initialize a genpd/genpd-of-provider pair when it's found.
> > +      */
> > +     for_each_child_of_node(np, node) {
> > +             if (!of_find_property(node, "#power-domain-cells", NULL))
> > +                     continue;
> > +
> > +             ret = psci_pd_init(node);
> > +             if (ret)
> > +                     goto put_node;
> > +
> > +             pd_count++;
> > +     }
> > +
> > +     /* Bail out if not using the hierarchical CPU topology. */
> > +     if (!pd_count)
> > +             goto out;
> > +
> > +     /* Link genpd masters/subdomains to model the CPU topology. */
> > +     ret = psci_pd_init_topology(np);
> > +     if (ret)
> > +             goto remove_pd;
> > +
> > +     /* Try to enable OSI mode. */
> > +     ret = psci_set_osi_mode();
> > +     if (ret)
> > +             pr_warn("failed to enable OSI mode: %d\n", ret);
>
> Same question as above: shouldn't we disable and goto remove_pd ?

See my answer above. Does it satisfy your concern?

If so, may I add your reviewed-by tag, for the next re-spin when I
have removed one of the compatible strings?

Kind regards
Uffe

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 13/14] cpuidle: psci: Add support for PM domains by using genpd
@ 2019-12-19 15:48       ` Ulf Hansson
  0 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-19 15:48 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: Mark Rutland, Lorenzo Pieralisi, Linux PM, Stephen Boyd,
	linux-arm-msm, Daniel Lezcano, Rafael J . Wysocki, Andy Gross,
	Lina Iyer, Bjorn Andersson, Kevin Hilman, Rob Herring, Linux ARM

On Thu, 19 Dec 2019 at 15:34, Sudeep Holla <sudeep.holla@arm.com> wrote:
>
> On Wed, Dec 11, 2019 at 04:43:42PM +0100, Ulf Hansson wrote:
> > When the hierarchical CPU topology layout is used in DT and the PSCI OSI
> > mode is supported by the PSCI FW, let's initialize a corresponding PM
> > domain topology by using genpd. This enables a CPU and a group of CPUs,
> > when attached to the topology, to be power-managed accordingly.
> >
> > To trigger the attempt to initialize the genpd data structures let's use a
> > subsys_initcall, which should be early enough to allow CPUs, but also other
> > devices to be attached.
> >
> > The initialization consists of parsing the PSCI OF node for the topology
> > and the "domain idle states" DT bindings. In case the idle states are
> > compatible with "domain-idle-state", the initialized genpd becomes
> > responsible of selecting an idle state for the PM domain, via assigning it
> > a genpd governor.
> >
> > Note that, a successful initialization of the genpd data structures, is
> > followed by a call to psci_set_osi_mode(), as to try to enable the OSI mode
> > in the PSCI FW. In case this fails, we fall back into a degraded mode
> > rather than bailing out and returning an error code.
> >
> > Co-developed-by: Lina Iyer <lina.iyer@linaro.org>
> > Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
> > Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> > ---
> >
> > Changes in v4:
> >       - None.
> >
> > ---
> >  drivers/cpuidle/cpuidle-psci-domain.c | 267 ++++++++++++++++++++++++++
> >  drivers/cpuidle/cpuidle-psci.c        |   4 +-
> >  drivers/cpuidle/cpuidle-psci.h        |   5 +
> >  3 files changed, 274 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/cpuidle/cpuidle-psci-domain.c b/drivers/cpuidle/cpuidle-psci-domain.c
> > index 656ef3d59149..c2f94ba42222 100644
> > --- a/drivers/cpuidle/cpuidle-psci-domain.c
> > +++ b/drivers/cpuidle/cpuidle-psci-domain.c
> > @@ -7,14 +7,281 @@
> >   *
> >   */
> >
> > +#define pr_fmt(fmt) "CPUidle PSCI: " fmt
> > +
> >  #include <linux/cpu.h>
> >  #include <linux/device.h>
> >  #include <linux/kernel.h>
> >  #include <linux/pm_domain.h>
> >  #include <linux/pm_runtime.h>
> > +#include <linux/psci.h>
> > +#include <linux/slab.h>
> > +#include <linux/string.h>
> >
> >  #include "cpuidle-psci.h"
> >
> > +struct psci_pd_provider {
> > +     struct list_head link;
> > +     struct device_node *node;
> > +};
> > +
> > +static LIST_HEAD(psci_pd_providers);
> > +static bool osi_mode_enabled;
> > +
> > +static int psci_pd_power_off(struct generic_pm_domain *pd)
> > +{
> > +     struct genpd_power_state *state = &pd->states[pd->state_idx];
> > +     u32 *pd_state;
> > +
> > +     /* If we have failed to enable OSI mode, then abort power off. */
> > +     if (!osi_mode_enabled)
> > +             return -EBUSY;
> > +
>
> Why is above check needed ? Shouldn't we have disable/remove pd of
> OSI is not enabled ?

Well, failing to enable OSI should in practice not happen, while it
theoretically it could.

My approach to this has been to fall back to use a "degraded mode",
which seems quite common for these kind of situations. The degraded
mode means, we are preventing domain states from being used.

More importantly, it also keeps the code registering the PM domains, a
bit simpler.

>
> > +     if (!state->data)
> > +             return 0;
> > +
> > +     /* OSI mode is enabled, set the corresponding domain state. */
> > +     pd_state = state->data;
> > +     psci_set_domain_state(*pd_state);
> > +
> > +     return 0;
> > +}
> > +
>
> [...]
>
> > +static const struct of_device_id psci_of_match[] __initconst = {
> > +     { .compatible = "arm,psci" },
>
> I think we can drop the above one as it's for v0.1 which didn't support
> OSI.

Yeah, I do that.

>
> > +     { .compatible = "arm,psci-0.2" },
> > +     { .compatible = "arm,psci-1.0" },
> > +     {}
> > +};
> > +
> > +static int __init psci_idle_init_domains(void)
> > +{
> > +     struct device_node *np = of_find_matching_node(NULL, psci_of_match);
> > +     struct device_node *node;
> > +     int ret = 0, pd_count = 0;
> > +
> > +     if (!np)
> > +             return -ENODEV;
> > +
> > +     /* Currently limit the hierarchical topology to be used in OSI mode. */
> > +     if (!psci_has_osi_support())
> > +             goto out;
> > +
> > +     /*
> > +      * Parse child nodes for the "#power-domain-cells" property and
> > +      * initialize a genpd/genpd-of-provider pair when it's found.
> > +      */
> > +     for_each_child_of_node(np, node) {
> > +             if (!of_find_property(node, "#power-domain-cells", NULL))
> > +                     continue;
> > +
> > +             ret = psci_pd_init(node);
> > +             if (ret)
> > +                     goto put_node;
> > +
> > +             pd_count++;
> > +     }
> > +
> > +     /* Bail out if not using the hierarchical CPU topology. */
> > +     if (!pd_count)
> > +             goto out;
> > +
> > +     /* Link genpd masters/subdomains to model the CPU topology. */
> > +     ret = psci_pd_init_topology(np);
> > +     if (ret)
> > +             goto remove_pd;
> > +
> > +     /* Try to enable OSI mode. */
> > +     ret = psci_set_osi_mode();
> > +     if (ret)
> > +             pr_warn("failed to enable OSI mode: %d\n", ret);
>
> Same question as above: shouldn't we disable and goto remove_pd ?

See my answer above. Does it satisfy your concern?

If so, may I add your reviewed-by tag, for the next re-spin when I
have removed one of the compatible strings?

Kind regards
Uffe

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 14/14] arm64: dts: Convert to the hierarchical CPU topology layout for MSM8916
  2019-12-19 14:34     ` Sudeep Holla
@ 2019-12-19 15:48       ` Ulf Hansson
  -1 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-19 15:48 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: Lorenzo Pieralisi, Rob Herring, Linux PM, Rafael J . Wysocki,
	Daniel Lezcano, Mark Rutland, Lina Iyer, Vincent Guittot,
	Stephen Boyd, Andy Gross, Bjorn Andersson, Kevin Hilman,
	Linux ARM, linux-arm-msm

On Thu, 19 Dec 2019 at 15:34, Sudeep Holla <sudeep.holla@arm.com> wrote:
>
> On Wed, Dec 11, 2019 at 04:43:43PM +0100, Ulf Hansson wrote:
> > To enable the OS to better support PSCI OS initiated CPU suspend mode,
> > let's convert from the flattened layout to the hierarchical layout.
> >
> > In the hierarchical layout, let's create a power domain provider per CPU
> > and describe the idle states for each CPU inside the power domain provider
> > node. To group the CPUs into a cluster, let's add another power domain
> > provider and make it act as the master domain. Note that, the CPU's idle
> > states remains compatible with "arm,idle-state", while the cluster's idle
> > state becomes compatible with "domain-idle-state".
> >
> > Co-developed-by: Lina Iyer <lina.iyer@linaro.org>
> > Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
> > Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> > ---
> >
> > Changes in v4:
> >       - None.
> >
> > ---
> >  arch/arm64/boot/dts/qcom/msm8916.dtsi | 57 +++++++++++++++++++++++++--
> >  1 file changed, 53 insertions(+), 4 deletions(-)
> >
> > diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> > index 8686e101905c..282c36c8fa3b 100644
> > --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
> > +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> > @@ -102,10 +102,11 @@
> >                       reg = <0x0>;
> >                       next-level-cache = <&L2_0>;
> >                       enable-method = "psci";
> > -                     cpu-idle-states = <&CPU_SLEEP_0>;
> >                       clocks = <&apcs>;
> >                       operating-points-v2 = <&cpu_opp_table>;
> >                       #cooling-cells = <2>;
> > +                     power-domains = <&CPU_PD0>;
> > +                     power-domain-names = "psci";
> >               };
> >
> >               CPU1: cpu@1 {
> > @@ -114,10 +115,11 @@
> >                       reg = <0x1>;
> >                       next-level-cache = <&L2_0>;
> >                       enable-method = "psci";
> > -                     cpu-idle-states = <&CPU_SLEEP_0>;
> >                       clocks = <&apcs>;
> >                       operating-points-v2 = <&cpu_opp_table>;
> >                       #cooling-cells = <2>;
> > +                     power-domains = <&CPU_PD1>;
> > +                     power-domain-names = "psci";
> >               };
> >
> >               CPU2: cpu@2 {
> > @@ -126,10 +128,11 @@
> >                       reg = <0x2>;
> >                       next-level-cache = <&L2_0>;
> >                       enable-method = "psci";
> > -                     cpu-idle-states = <&CPU_SLEEP_0>;
> >                       clocks = <&apcs>;
> >                       operating-points-v2 = <&cpu_opp_table>;
> >                       #cooling-cells = <2>;
> > +                     power-domains = <&CPU_PD2>;
> > +                     power-domain-names = "psci";
> >               };
> >
> >               CPU3: cpu@3 {
> > @@ -138,10 +141,11 @@
> >                       reg = <0x3>;
> >                       next-level-cache = <&L2_0>;
> >                       enable-method = "psci";
> > -                     cpu-idle-states = <&CPU_SLEEP_0>;
> >                       clocks = <&apcs>;
> >                       operating-points-v2 = <&cpu_opp_table>;
> >                       #cooling-cells = <2>;
> > +                     power-domains = <&CPU_PD3>;
> > +                     power-domain-names = "psci";
> >               };
> >
> >               L2_0: l2-cache {
> > @@ -161,12 +165,57 @@
> >                               min-residency-us = <2000>;
> >                               local-timer-stop;
> >                       };
> > +
> > +                     CLUSTER_RET: cluster-retention {
> > +                             compatible = "domain-idle-state";
> > +                             arm,psci-suspend-param = <0x41000012>;
>
> If I followed the thread correctly, we are now just using the param as is
> without any extra logic like ORing like before. i.e. The domain state
> parameter overrides the any param below it in the hierarchy.
>
> If that's correct, then

That's correct!

> Acked-by: Sudeep Holla <sudeep.holla@arm.com>

Thanks!

Kind regards
Uffe

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 14/14] arm64: dts: Convert to the hierarchical CPU topology layout for MSM8916
@ 2019-12-19 15:48       ` Ulf Hansson
  0 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-19 15:48 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: Mark Rutland, Lorenzo Pieralisi, Linux PM, Stephen Boyd,
	linux-arm-msm, Daniel Lezcano, Rafael J . Wysocki, Andy Gross,
	Lina Iyer, Bjorn Andersson, Kevin Hilman, Rob Herring, Linux ARM

On Thu, 19 Dec 2019 at 15:34, Sudeep Holla <sudeep.holla@arm.com> wrote:
>
> On Wed, Dec 11, 2019 at 04:43:43PM +0100, Ulf Hansson wrote:
> > To enable the OS to better support PSCI OS initiated CPU suspend mode,
> > let's convert from the flattened layout to the hierarchical layout.
> >
> > In the hierarchical layout, let's create a power domain provider per CPU
> > and describe the idle states for each CPU inside the power domain provider
> > node. To group the CPUs into a cluster, let's add another power domain
> > provider and make it act as the master domain. Note that, the CPU's idle
> > states remains compatible with "arm,idle-state", while the cluster's idle
> > state becomes compatible with "domain-idle-state".
> >
> > Co-developed-by: Lina Iyer <lina.iyer@linaro.org>
> > Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
> > Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> > ---
> >
> > Changes in v4:
> >       - None.
> >
> > ---
> >  arch/arm64/boot/dts/qcom/msm8916.dtsi | 57 +++++++++++++++++++++++++--
> >  1 file changed, 53 insertions(+), 4 deletions(-)
> >
> > diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> > index 8686e101905c..282c36c8fa3b 100644
> > --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
> > +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> > @@ -102,10 +102,11 @@
> >                       reg = <0x0>;
> >                       next-level-cache = <&L2_0>;
> >                       enable-method = "psci";
> > -                     cpu-idle-states = <&CPU_SLEEP_0>;
> >                       clocks = <&apcs>;
> >                       operating-points-v2 = <&cpu_opp_table>;
> >                       #cooling-cells = <2>;
> > +                     power-domains = <&CPU_PD0>;
> > +                     power-domain-names = "psci";
> >               };
> >
> >               CPU1: cpu@1 {
> > @@ -114,10 +115,11 @@
> >                       reg = <0x1>;
> >                       next-level-cache = <&L2_0>;
> >                       enable-method = "psci";
> > -                     cpu-idle-states = <&CPU_SLEEP_0>;
> >                       clocks = <&apcs>;
> >                       operating-points-v2 = <&cpu_opp_table>;
> >                       #cooling-cells = <2>;
> > +                     power-domains = <&CPU_PD1>;
> > +                     power-domain-names = "psci";
> >               };
> >
> >               CPU2: cpu@2 {
> > @@ -126,10 +128,11 @@
> >                       reg = <0x2>;
> >                       next-level-cache = <&L2_0>;
> >                       enable-method = "psci";
> > -                     cpu-idle-states = <&CPU_SLEEP_0>;
> >                       clocks = <&apcs>;
> >                       operating-points-v2 = <&cpu_opp_table>;
> >                       #cooling-cells = <2>;
> > +                     power-domains = <&CPU_PD2>;
> > +                     power-domain-names = "psci";
> >               };
> >
> >               CPU3: cpu@3 {
> > @@ -138,10 +141,11 @@
> >                       reg = <0x3>;
> >                       next-level-cache = <&L2_0>;
> >                       enable-method = "psci";
> > -                     cpu-idle-states = <&CPU_SLEEP_0>;
> >                       clocks = <&apcs>;
> >                       operating-points-v2 = <&cpu_opp_table>;
> >                       #cooling-cells = <2>;
> > +                     power-domains = <&CPU_PD3>;
> > +                     power-domain-names = "psci";
> >               };
> >
> >               L2_0: l2-cache {
> > @@ -161,12 +165,57 @@
> >                               min-residency-us = <2000>;
> >                               local-timer-stop;
> >                       };
> > +
> > +                     CLUSTER_RET: cluster-retention {
> > +                             compatible = "domain-idle-state";
> > +                             arm,psci-suspend-param = <0x41000012>;
>
> If I followed the thread correctly, we are now just using the param as is
> without any extra logic like ORing like before. i.e. The domain state
> parameter overrides the any param below it in the hierarchy.
>
> If that's correct, then

That's correct!

> Acked-by: Sudeep Holla <sudeep.holla@arm.com>

Thanks!

Kind regards
Uffe

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 14/14] arm64: dts: Convert to the hierarchical CPU topology layout for MSM8916
  2019-12-19 15:48       ` Ulf Hansson
@ 2019-12-19 17:58         ` Sudeep Holla
  -1 siblings, 0 replies; 76+ messages in thread
From: Sudeep Holla @ 2019-12-19 17:58 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Lorenzo Pieralisi, Rob Herring, Linux PM, Rafael J . Wysocki,
	Daniel Lezcano, Mark Rutland, Lina Iyer, Vincent Guittot,
	Stephen Boyd, Andy Gross, Bjorn Andersson, Kevin Hilman,
	Sudeep Holla, Linux ARM, linux-arm-msm

On Thu, Dec 19, 2019 at 04:48:47PM +0100, Ulf Hansson wrote:
> On Thu, 19 Dec 2019 at 15:34, Sudeep Holla <sudeep.holla@arm.com> wrote:
> >
> > On Wed, Dec 11, 2019 at 04:43:43PM +0100, Ulf Hansson wrote:
> > > To enable the OS to better support PSCI OS initiated CPU suspend mode,
> > > let's convert from the flattened layout to the hierarchical layout.
> > >
> > > In the hierarchical layout, let's create a power domain provider per CPU
> > > and describe the idle states for each CPU inside the power domain provider
> > > node. To group the CPUs into a cluster, let's add another power domain
> > > provider and make it act as the master domain. Note that, the CPU's idle
> > > states remains compatible with "arm,idle-state", while the cluster's idle
> > > state becomes compatible with "domain-idle-state".
> > >
> > > Co-developed-by: Lina Iyer <lina.iyer@linaro.org>
> > > Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
> > > Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> > > ---
> > >
> > > Changes in v4:
> > >       - None.
> > >
> > > ---
> > >  arch/arm64/boot/dts/qcom/msm8916.dtsi | 57 +++++++++++++++++++++++++--
> > >  1 file changed, 53 insertions(+), 4 deletions(-)
> > >
> > > diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> > > index 8686e101905c..282c36c8fa3b 100644
> > > --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
> > > +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> > > @@ -102,10 +102,11 @@
> > >                       reg = <0x0>;
> > >                       next-level-cache = <&L2_0>;
> > >                       enable-method = "psci";
> > > -                     cpu-idle-states = <&CPU_SLEEP_0>;
> > >                       clocks = <&apcs>;
> > >                       operating-points-v2 = <&cpu_opp_table>;
> > >                       #cooling-cells = <2>;
> > > +                     power-domains = <&CPU_PD0>;
> > > +                     power-domain-names = "psci";
> > >               };
> > >
> > >               CPU1: cpu@1 {
> > > @@ -114,10 +115,11 @@
> > >                       reg = <0x1>;
> > >                       next-level-cache = <&L2_0>;
> > >                       enable-method = "psci";
> > > -                     cpu-idle-states = <&CPU_SLEEP_0>;
> > >                       clocks = <&apcs>;
> > >                       operating-points-v2 = <&cpu_opp_table>;
> > >                       #cooling-cells = <2>;
> > > +                     power-domains = <&CPU_PD1>;
> > > +                     power-domain-names = "psci";
> > >               };
> > >
> > >               CPU2: cpu@2 {
> > > @@ -126,10 +128,11 @@
> > >                       reg = <0x2>;
> > >                       next-level-cache = <&L2_0>;
> > >                       enable-method = "psci";
> > > -                     cpu-idle-states = <&CPU_SLEEP_0>;
> > >                       clocks = <&apcs>;
> > >                       operating-points-v2 = <&cpu_opp_table>;
> > >                       #cooling-cells = <2>;
> > > +                     power-domains = <&CPU_PD2>;
> > > +                     power-domain-names = "psci";
> > >               };
> > >
> > >               CPU3: cpu@3 {
> > > @@ -138,10 +141,11 @@
> > >                       reg = <0x3>;
> > >                       next-level-cache = <&L2_0>;
> > >                       enable-method = "psci";
> > > -                     cpu-idle-states = <&CPU_SLEEP_0>;
> > >                       clocks = <&apcs>;
> > >                       operating-points-v2 = <&cpu_opp_table>;
> > >                       #cooling-cells = <2>;
> > > +                     power-domains = <&CPU_PD3>;
> > > +                     power-domain-names = "psci";
> > >               };
> > >
> > >               L2_0: l2-cache {
> > > @@ -161,12 +165,57 @@
> > >                               min-residency-us = <2000>;
> > >                               local-timer-stop;
> > >                       };
> > > +
> > > +                     CLUSTER_RET: cluster-retention {
> > > +                             compatible = "domain-idle-state";
> > > +                             arm,psci-suspend-param = <0x41000012>;
> >
> > If I followed the thread correctly, we are now just using the param as is
> > without any extra logic like ORing like before. i.e. The domain state
> > parameter overrides the any param below it in the hierarchy.
> >
> > If that's correct, then
>
> That's correct!
>

Thanks for the confirmation.

--
Regards,
Sudeep

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 14/14] arm64: dts: Convert to the hierarchical CPU topology layout for MSM8916
@ 2019-12-19 17:58         ` Sudeep Holla
  0 siblings, 0 replies; 76+ messages in thread
From: Sudeep Holla @ 2019-12-19 17:58 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Mark Rutland, Lorenzo Pieralisi, Linux PM, Stephen Boyd,
	linux-arm-msm, Daniel Lezcano, Rafael J . Wysocki, Andy Gross,
	Lina Iyer, Bjorn Andersson, Kevin Hilman, Rob Herring,
	Sudeep Holla, Linux ARM

On Thu, Dec 19, 2019 at 04:48:47PM +0100, Ulf Hansson wrote:
> On Thu, 19 Dec 2019 at 15:34, Sudeep Holla <sudeep.holla@arm.com> wrote:
> >
> > On Wed, Dec 11, 2019 at 04:43:43PM +0100, Ulf Hansson wrote:
> > > To enable the OS to better support PSCI OS initiated CPU suspend mode,
> > > let's convert from the flattened layout to the hierarchical layout.
> > >
> > > In the hierarchical layout, let's create a power domain provider per CPU
> > > and describe the idle states for each CPU inside the power domain provider
> > > node. To group the CPUs into a cluster, let's add another power domain
> > > provider and make it act as the master domain. Note that, the CPU's idle
> > > states remains compatible with "arm,idle-state", while the cluster's idle
> > > state becomes compatible with "domain-idle-state".
> > >
> > > Co-developed-by: Lina Iyer <lina.iyer@linaro.org>
> > > Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
> > > Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> > > ---
> > >
> > > Changes in v4:
> > >       - None.
> > >
> > > ---
> > >  arch/arm64/boot/dts/qcom/msm8916.dtsi | 57 +++++++++++++++++++++++++--
> > >  1 file changed, 53 insertions(+), 4 deletions(-)
> > >
> > > diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> > > index 8686e101905c..282c36c8fa3b 100644
> > > --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
> > > +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> > > @@ -102,10 +102,11 @@
> > >                       reg = <0x0>;
> > >                       next-level-cache = <&L2_0>;
> > >                       enable-method = "psci";
> > > -                     cpu-idle-states = <&CPU_SLEEP_0>;
> > >                       clocks = <&apcs>;
> > >                       operating-points-v2 = <&cpu_opp_table>;
> > >                       #cooling-cells = <2>;
> > > +                     power-domains = <&CPU_PD0>;
> > > +                     power-domain-names = "psci";
> > >               };
> > >
> > >               CPU1: cpu@1 {
> > > @@ -114,10 +115,11 @@
> > >                       reg = <0x1>;
> > >                       next-level-cache = <&L2_0>;
> > >                       enable-method = "psci";
> > > -                     cpu-idle-states = <&CPU_SLEEP_0>;
> > >                       clocks = <&apcs>;
> > >                       operating-points-v2 = <&cpu_opp_table>;
> > >                       #cooling-cells = <2>;
> > > +                     power-domains = <&CPU_PD1>;
> > > +                     power-domain-names = "psci";
> > >               };
> > >
> > >               CPU2: cpu@2 {
> > > @@ -126,10 +128,11 @@
> > >                       reg = <0x2>;
> > >                       next-level-cache = <&L2_0>;
> > >                       enable-method = "psci";
> > > -                     cpu-idle-states = <&CPU_SLEEP_0>;
> > >                       clocks = <&apcs>;
> > >                       operating-points-v2 = <&cpu_opp_table>;
> > >                       #cooling-cells = <2>;
> > > +                     power-domains = <&CPU_PD2>;
> > > +                     power-domain-names = "psci";
> > >               };
> > >
> > >               CPU3: cpu@3 {
> > > @@ -138,10 +141,11 @@
> > >                       reg = <0x3>;
> > >                       next-level-cache = <&L2_0>;
> > >                       enable-method = "psci";
> > > -                     cpu-idle-states = <&CPU_SLEEP_0>;
> > >                       clocks = <&apcs>;
> > >                       operating-points-v2 = <&cpu_opp_table>;
> > >                       #cooling-cells = <2>;
> > > +                     power-domains = <&CPU_PD3>;
> > > +                     power-domain-names = "psci";
> > >               };
> > >
> > >               L2_0: l2-cache {
> > > @@ -161,12 +165,57 @@
> > >                               min-residency-us = <2000>;
> > >                               local-timer-stop;
> > >                       };
> > > +
> > > +                     CLUSTER_RET: cluster-retention {
> > > +                             compatible = "domain-idle-state";
> > > +                             arm,psci-suspend-param = <0x41000012>;
> >
> > If I followed the thread correctly, we are now just using the param as is
> > without any extra logic like ORing like before. i.e. The domain state
> > parameter overrides the any param below it in the hierarchy.
> >
> > If that's correct, then
>
> That's correct!
>

Thanks for the confirmation.

--
Regards,
Sudeep

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 10/14] cpuidle: psci: Prepare to use OS initiated suspend mode via PM domains
  2019-12-19 15:48       ` Ulf Hansson
@ 2019-12-19 18:01         ` Sudeep Holla
  -1 siblings, 0 replies; 76+ messages in thread
From: Sudeep Holla @ 2019-12-19 18:01 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Lorenzo Pieralisi, Rob Herring, Linux PM, Rafael J . Wysocki,
	Daniel Lezcano, Mark Rutland, Lina Iyer, Vincent Guittot,
	Stephen Boyd, Andy Gross, Bjorn Andersson, Kevin Hilman,
	Sudeep Holla, Linux ARM, linux-arm-msm

On Thu, Dec 19, 2019 at 04:48:13PM +0100, Ulf Hansson wrote:
> On Thu, 19 Dec 2019 at 15:32, Sudeep Holla <sudeep.holla@arm.com> wrote:
> >
> > On Wed, Dec 11, 2019 at 04:43:39PM +0100, Ulf Hansson wrote:
> > > The per CPU variable psci_power_state, contains an array of fixed values,
> > > which reflects the corresponding arm,psci-suspend-param parsed from DT, for
> > > each of the available CPU idle states.
> > >
> > > This isn't sufficient when using the hierarchical CPU topology in DT, in
> > > combination with having PSCI OS initiated (OSI) mode enabled. More
> > > precisely, in OSI mode, Linux is responsible of telling the PSCI FW what
> > > idle state the cluster (a group of CPUs) should enter, while in PSCI
> > > Platform Coordinated (PC) mode, each CPU independently votes for an idle
> > > state of the cluster.
> > >
> > > For this reason, introduce a per CPU variable called domain_state and
> > > implement two helper functions to read/write its value. Then let the
> > > domain_state take precedence over the regular selected state, when entering
> > > and idle state.
> > >
> > > To avoid executing the above OSI specific code in the ->enter() callback,
> > > while operating in the default PSCI Platform Coordinated mode, let's also
> > > add a new enter-function and use it for OSI.
> > >
> > > Co-developed-by: Lina Iyer <lina.iyer@linaro.org>
> > > Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
> > > Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> > > ---
> > >
> > > Changes in v4:
> > >       - Rebased on top of earlier changes.
> > >       - Add comment about using the deepest cpuidle state for the domain state
> > >       selection.
> > >
> > > ---
> > >  drivers/cpuidle/cpuidle-psci.c | 56 ++++++++++++++++++++++++++++++----
> > >  1 file changed, 50 insertions(+), 6 deletions(-)
> > >
> > > diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c
> > > index 6a87848be3c3..9600fe674a89 100644
> > > --- a/drivers/cpuidle/cpuidle-psci.c
> > > +++ b/drivers/cpuidle/cpuidle-psci.c
> > > @@ -29,14 +29,47 @@ struct psci_cpuidle_data {
> > >  };
> > >
> > >  static DEFINE_PER_CPU_READ_MOSTLY(struct psci_cpuidle_data, psci_cpuidle_data);
> > > +static DEFINE_PER_CPU(u32, domain_state);
> > > +
> >
> > [...]
> >
> > > +static int psci_enter_domain_idle_state(struct cpuidle_device *dev,
> > > +                                     struct cpuidle_driver *drv, int idx)
> > > +{
> > > +     struct psci_cpuidle_data *data = this_cpu_ptr(&psci_cpuidle_data);
> > > +     u32 *states = data->psci_states;
> >
> > Why can't the above be like this for consistency(see below in
> > psci_enter_idle_state) ?
>
> You have a point, however in patch11 I am adding this line below.
>
> struct device *pd_dev = data->dev;
>
> So I don't think it matters much, agree?
>

Ah OK, looked odd as part of this patch, may be you could have moved
this change into that patch. Anyways fine as is.

> >
> >         u32 *states = __this_cpu_read(psci_cpuidle_data.psci_states);
> >
> > > +     u32 state = psci_get_domain_state();
> > > +     int ret;
> > > +
> > > +     if (!state)
> > > +             state = states[idx];
> > > +
> > > +     ret = psci_enter_state(idx, state);
> > > +
> > > +     /* Clear the domain state to start fresh when back from idle. */
> > > +     psci_set_domain_state(0);
> > > +     return ret;
> > > +}
> > >
> >
> > [...]
> >
> > > @@ -118,6 +152,15 @@ static int __init psci_dt_cpu_init_idle(struct device_node *cpu_node,
> > >                       ret = PTR_ERR(data->dev);
> > >                       goto free_mem;
> > >               }
> > > +
> > > +             /*
> > > +              * Using the deepest state for the CPU to trigger a potential
> > > +              * selection of a shared state for the domain, assumes the
> > > +              * domain states are all deeper states.
> > > +              */
> > > +             if (data->dev)
> >
> > You can drop this check as return on error above.
>
> Actually not, because if OSI is supported, there is still a
> possibility that the PM domain topology isn't used.
>

And how do we support that ? I am missing something here.

> This means ->data->dev is NULL.
>

I don't get that.

> >
> > > +                     drv->states[state_count - 1].enter =
> > > +                             psci_enter_domain_idle_state;
> >
> > I see the comment above but this potential blocks retention mode at
> > cluster level when all cpu enter retention at CPU level. I don't like
> > this assumption, but I don't have any better suggestion. Please add the
> > note that we can't enter RETENTION state at cluster/domain level when
> > all CPUs enter at CPU level.
>
> You are correct, but I think the comment a few lines above (agreed to
> be added by Lorenzo in the previous version) should be enough to
> explain that. No?
>
> The point is, this is only a problem if cluster RETENTION is
> considered to be a shallower state that CPU power off, for example.
>

Yes, but give examples makes it better and helps people who may be
wondering why cluster retention state is not being entered. You can just
add to the above comment:

"e.g. If CPU Retention is one of the shallower state, then we can't enter
any of the allowed domain states."

> >
> > As I wrote above I got another doubt. What if platform specifies just
> > RETENTION state at CPU as well as Cluster/domain ? I think it should be
> > fine, just asking it out loud.
>
> It's fine.
>
> However, I am looking at what future improvements that can be made.
> This is one of them, but let's discuss that later on.
>

OK

--
Regards,
Sudeep

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 10/14] cpuidle: psci: Prepare to use OS initiated suspend mode via PM domains
@ 2019-12-19 18:01         ` Sudeep Holla
  0 siblings, 0 replies; 76+ messages in thread
From: Sudeep Holla @ 2019-12-19 18:01 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Mark Rutland, Lorenzo Pieralisi, Linux PM, Stephen Boyd,
	linux-arm-msm, Daniel Lezcano, Rafael J . Wysocki, Andy Gross,
	Lina Iyer, Bjorn Andersson, Kevin Hilman, Rob Herring,
	Sudeep Holla, Linux ARM

On Thu, Dec 19, 2019 at 04:48:13PM +0100, Ulf Hansson wrote:
> On Thu, 19 Dec 2019 at 15:32, Sudeep Holla <sudeep.holla@arm.com> wrote:
> >
> > On Wed, Dec 11, 2019 at 04:43:39PM +0100, Ulf Hansson wrote:
> > > The per CPU variable psci_power_state, contains an array of fixed values,
> > > which reflects the corresponding arm,psci-suspend-param parsed from DT, for
> > > each of the available CPU idle states.
> > >
> > > This isn't sufficient when using the hierarchical CPU topology in DT, in
> > > combination with having PSCI OS initiated (OSI) mode enabled. More
> > > precisely, in OSI mode, Linux is responsible of telling the PSCI FW what
> > > idle state the cluster (a group of CPUs) should enter, while in PSCI
> > > Platform Coordinated (PC) mode, each CPU independently votes for an idle
> > > state of the cluster.
> > >
> > > For this reason, introduce a per CPU variable called domain_state and
> > > implement two helper functions to read/write its value. Then let the
> > > domain_state take precedence over the regular selected state, when entering
> > > and idle state.
> > >
> > > To avoid executing the above OSI specific code in the ->enter() callback,
> > > while operating in the default PSCI Platform Coordinated mode, let's also
> > > add a new enter-function and use it for OSI.
> > >
> > > Co-developed-by: Lina Iyer <lina.iyer@linaro.org>
> > > Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
> > > Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> > > ---
> > >
> > > Changes in v4:
> > >       - Rebased on top of earlier changes.
> > >       - Add comment about using the deepest cpuidle state for the domain state
> > >       selection.
> > >
> > > ---
> > >  drivers/cpuidle/cpuidle-psci.c | 56 ++++++++++++++++++++++++++++++----
> > >  1 file changed, 50 insertions(+), 6 deletions(-)
> > >
> > > diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c
> > > index 6a87848be3c3..9600fe674a89 100644
> > > --- a/drivers/cpuidle/cpuidle-psci.c
> > > +++ b/drivers/cpuidle/cpuidle-psci.c
> > > @@ -29,14 +29,47 @@ struct psci_cpuidle_data {
> > >  };
> > >
> > >  static DEFINE_PER_CPU_READ_MOSTLY(struct psci_cpuidle_data, psci_cpuidle_data);
> > > +static DEFINE_PER_CPU(u32, domain_state);
> > > +
> >
> > [...]
> >
> > > +static int psci_enter_domain_idle_state(struct cpuidle_device *dev,
> > > +                                     struct cpuidle_driver *drv, int idx)
> > > +{
> > > +     struct psci_cpuidle_data *data = this_cpu_ptr(&psci_cpuidle_data);
> > > +     u32 *states = data->psci_states;
> >
> > Why can't the above be like this for consistency(see below in
> > psci_enter_idle_state) ?
>
> You have a point, however in patch11 I am adding this line below.
>
> struct device *pd_dev = data->dev;
>
> So I don't think it matters much, agree?
>

Ah OK, looked odd as part of this patch, may be you could have moved
this change into that patch. Anyways fine as is.

> >
> >         u32 *states = __this_cpu_read(psci_cpuidle_data.psci_states);
> >
> > > +     u32 state = psci_get_domain_state();
> > > +     int ret;
> > > +
> > > +     if (!state)
> > > +             state = states[idx];
> > > +
> > > +     ret = psci_enter_state(idx, state);
> > > +
> > > +     /* Clear the domain state to start fresh when back from idle. */
> > > +     psci_set_domain_state(0);
> > > +     return ret;
> > > +}
> > >
> >
> > [...]
> >
> > > @@ -118,6 +152,15 @@ static int __init psci_dt_cpu_init_idle(struct device_node *cpu_node,
> > >                       ret = PTR_ERR(data->dev);
> > >                       goto free_mem;
> > >               }
> > > +
> > > +             /*
> > > +              * Using the deepest state for the CPU to trigger a potential
> > > +              * selection of a shared state for the domain, assumes the
> > > +              * domain states are all deeper states.
> > > +              */
> > > +             if (data->dev)
> >
> > You can drop this check as return on error above.
>
> Actually not, because if OSI is supported, there is still a
> possibility that the PM domain topology isn't used.
>

And how do we support that ? I am missing something here.

> This means ->data->dev is NULL.
>

I don't get that.

> >
> > > +                     drv->states[state_count - 1].enter =
> > > +                             psci_enter_domain_idle_state;
> >
> > I see the comment above but this potential blocks retention mode at
> > cluster level when all cpu enter retention at CPU level. I don't like
> > this assumption, but I don't have any better suggestion. Please add the
> > note that we can't enter RETENTION state at cluster/domain level when
> > all CPUs enter at CPU level.
>
> You are correct, but I think the comment a few lines above (agreed to
> be added by Lorenzo in the previous version) should be enough to
> explain that. No?
>
> The point is, this is only a problem if cluster RETENTION is
> considered to be a shallower state that CPU power off, for example.
>

Yes, but give examples makes it better and helps people who may be
wondering why cluster retention state is not being entered. You can just
add to the above comment:

"e.g. If CPU Retention is one of the shallower state, then we can't enter
any of the allowed domain states."

> >
> > As I wrote above I got another doubt. What if platform specifies just
> > RETENTION state at CPU as well as Cluster/domain ? I think it should be
> > fine, just asking it out loud.
>
> It's fine.
>
> However, I am looking at what future improvements that can be made.
> This is one of them, but let's discuss that later on.
>

OK

--
Regards,
Sudeep

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 13/14] cpuidle: psci: Add support for PM domains by using genpd
  2019-12-19 15:48       ` Ulf Hansson
@ 2019-12-19 18:06         ` Sudeep Holla
  -1 siblings, 0 replies; 76+ messages in thread
From: Sudeep Holla @ 2019-12-19 18:06 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Lorenzo Pieralisi, Rob Herring, Linux PM, Rafael J . Wysocki,
	Daniel Lezcano, Mark Rutland, Lina Iyer, Vincent Guittot,
	Stephen Boyd, Andy Gross, Bjorn Andersson, Kevin Hilman,
	Linux ARM, linux-arm-msm

On Thu, Dec 19, 2019 at 04:48:39PM +0100, Ulf Hansson wrote:
> On Thu, 19 Dec 2019 at 15:34, Sudeep Holla <sudeep.holla@arm.com> wrote:
> >
> > On Wed, Dec 11, 2019 at 04:43:42PM +0100, Ulf Hansson wrote:
> > > When the hierarchical CPU topology layout is used in DT and the PSCI OSI
> > > mode is supported by the PSCI FW, let's initialize a corresponding PM
> > > domain topology by using genpd. This enables a CPU and a group of CPUs,
> > > when attached to the topology, to be power-managed accordingly.
> > >
> > > To trigger the attempt to initialize the genpd data structures let's use a
> > > subsys_initcall, which should be early enough to allow CPUs, but also other
> > > devices to be attached.
> > >
> > > The initialization consists of parsing the PSCI OF node for the topology
> > > and the "domain idle states" DT bindings. In case the idle states are
> > > compatible with "domain-idle-state", the initialized genpd becomes
> > > responsible of selecting an idle state for the PM domain, via assigning it
> > > a genpd governor.
> > >
> > > Note that, a successful initialization of the genpd data structures, is
> > > followed by a call to psci_set_osi_mode(), as to try to enable the OSI mode
> > > in the PSCI FW. In case this fails, we fall back into a degraded mode
> > > rather than bailing out and returning an error code.
> > >
> > > Co-developed-by: Lina Iyer <lina.iyer@linaro.org>
> > > Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
> > > Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> > > ---
> > >
> > > Changes in v4:
> > >       - None.
> > >
> > > ---
> > >  drivers/cpuidle/cpuidle-psci-domain.c | 267 ++++++++++++++++++++++++++
> > >  drivers/cpuidle/cpuidle-psci.c        |   4 +-
> > >  drivers/cpuidle/cpuidle-psci.h        |   5 +
> > >  3 files changed, 274 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/drivers/cpuidle/cpuidle-psci-domain.c b/drivers/cpuidle/cpuidle-psci-domain.c
> > > index 656ef3d59149..c2f94ba42222 100644
> > > --- a/drivers/cpuidle/cpuidle-psci-domain.c
> > > +++ b/drivers/cpuidle/cpuidle-psci-domain.c
> > > @@ -7,14 +7,281 @@
> > >   *
> > >   */
> > >
> > > +#define pr_fmt(fmt) "CPUidle PSCI: " fmt
> > > +
> > >  #include <linux/cpu.h>
> > >  #include <linux/device.h>
> > >  #include <linux/kernel.h>
> > >  #include <linux/pm_domain.h>
> > >  #include <linux/pm_runtime.h>
> > > +#include <linux/psci.h>
> > > +#include <linux/slab.h>
> > > +#include <linux/string.h>
> > >
> > >  #include "cpuidle-psci.h"
> > >
> > > +struct psci_pd_provider {
> > > +     struct list_head link;
> > > +     struct device_node *node;
> > > +};
> > > +
> > > +static LIST_HEAD(psci_pd_providers);
> > > +static bool osi_mode_enabled;
> > > +
> > > +static int psci_pd_power_off(struct generic_pm_domain *pd)
> > > +{
> > > +     struct genpd_power_state *state = &pd->states[pd->state_idx];
> > > +     u32 *pd_state;
> > > +
> > > +     /* If we have failed to enable OSI mode, then abort power off. */
> > > +     if (!osi_mode_enabled)
> > > +             return -EBUSY;
> > > +
> >
> > Why is above check needed ? Shouldn't we have disable/remove pd of
> > OSI is not enabled ?
>
> Well, failing to enable OSI should in practice not happen, while it
> theoretically it could.
>

I won't assume that. Since it's new and not tested yet, I prefer to assume
it can fail.

> My approach to this has been to fall back to use a "degraded mode",
> which seems quite common for these kind of situations. The degraded
> mode means, we are preventing domain states from being used.
>

But why can't we just fail registering or remove if already added.
They are useless for "degraded mode" anyways. And it will ensure that
data->dev is NULL. Sorry now I see why you said it can be NULL but I
would rather not leave those unused genpd in place in case of error.

> More importantly, it also keeps the code registering the PM domains, a
> bit simpler.
>

I feel it is simpler other way around especially if I am testing and
seeing failures but I see genpd succeeding. That's confusing.

--
Regards,
Sudeep

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 13/14] cpuidle: psci: Add support for PM domains by using genpd
@ 2019-12-19 18:06         ` Sudeep Holla
  0 siblings, 0 replies; 76+ messages in thread
From: Sudeep Holla @ 2019-12-19 18:06 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Mark Rutland, Lorenzo Pieralisi, Linux PM, Stephen Boyd,
	linux-arm-msm, Daniel Lezcano, Rafael J . Wysocki, Andy Gross,
	Lina Iyer, Bjorn Andersson, Kevin Hilman, Rob Herring, Linux ARM

On Thu, Dec 19, 2019 at 04:48:39PM +0100, Ulf Hansson wrote:
> On Thu, 19 Dec 2019 at 15:34, Sudeep Holla <sudeep.holla@arm.com> wrote:
> >
> > On Wed, Dec 11, 2019 at 04:43:42PM +0100, Ulf Hansson wrote:
> > > When the hierarchical CPU topology layout is used in DT and the PSCI OSI
> > > mode is supported by the PSCI FW, let's initialize a corresponding PM
> > > domain topology by using genpd. This enables a CPU and a group of CPUs,
> > > when attached to the topology, to be power-managed accordingly.
> > >
> > > To trigger the attempt to initialize the genpd data structures let's use a
> > > subsys_initcall, which should be early enough to allow CPUs, but also other
> > > devices to be attached.
> > >
> > > The initialization consists of parsing the PSCI OF node for the topology
> > > and the "domain idle states" DT bindings. In case the idle states are
> > > compatible with "domain-idle-state", the initialized genpd becomes
> > > responsible of selecting an idle state for the PM domain, via assigning it
> > > a genpd governor.
> > >
> > > Note that, a successful initialization of the genpd data structures, is
> > > followed by a call to psci_set_osi_mode(), as to try to enable the OSI mode
> > > in the PSCI FW. In case this fails, we fall back into a degraded mode
> > > rather than bailing out and returning an error code.
> > >
> > > Co-developed-by: Lina Iyer <lina.iyer@linaro.org>
> > > Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
> > > Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> > > ---
> > >
> > > Changes in v4:
> > >       - None.
> > >
> > > ---
> > >  drivers/cpuidle/cpuidle-psci-domain.c | 267 ++++++++++++++++++++++++++
> > >  drivers/cpuidle/cpuidle-psci.c        |   4 +-
> > >  drivers/cpuidle/cpuidle-psci.h        |   5 +
> > >  3 files changed, 274 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/drivers/cpuidle/cpuidle-psci-domain.c b/drivers/cpuidle/cpuidle-psci-domain.c
> > > index 656ef3d59149..c2f94ba42222 100644
> > > --- a/drivers/cpuidle/cpuidle-psci-domain.c
> > > +++ b/drivers/cpuidle/cpuidle-psci-domain.c
> > > @@ -7,14 +7,281 @@
> > >   *
> > >   */
> > >
> > > +#define pr_fmt(fmt) "CPUidle PSCI: " fmt
> > > +
> > >  #include <linux/cpu.h>
> > >  #include <linux/device.h>
> > >  #include <linux/kernel.h>
> > >  #include <linux/pm_domain.h>
> > >  #include <linux/pm_runtime.h>
> > > +#include <linux/psci.h>
> > > +#include <linux/slab.h>
> > > +#include <linux/string.h>
> > >
> > >  #include "cpuidle-psci.h"
> > >
> > > +struct psci_pd_provider {
> > > +     struct list_head link;
> > > +     struct device_node *node;
> > > +};
> > > +
> > > +static LIST_HEAD(psci_pd_providers);
> > > +static bool osi_mode_enabled;
> > > +
> > > +static int psci_pd_power_off(struct generic_pm_domain *pd)
> > > +{
> > > +     struct genpd_power_state *state = &pd->states[pd->state_idx];
> > > +     u32 *pd_state;
> > > +
> > > +     /* If we have failed to enable OSI mode, then abort power off. */
> > > +     if (!osi_mode_enabled)
> > > +             return -EBUSY;
> > > +
> >
> > Why is above check needed ? Shouldn't we have disable/remove pd of
> > OSI is not enabled ?
>
> Well, failing to enable OSI should in practice not happen, while it
> theoretically it could.
>

I won't assume that. Since it's new and not tested yet, I prefer to assume
it can fail.

> My approach to this has been to fall back to use a "degraded mode",
> which seems quite common for these kind of situations. The degraded
> mode means, we are preventing domain states from being used.
>

But why can't we just fail registering or remove if already added.
They are useless for "degraded mode" anyways. And it will ensure that
data->dev is NULL. Sorry now I see why you said it can be NULL but I
would rather not leave those unused genpd in place in case of error.

> More importantly, it also keeps the code registering the PM domains, a
> bit simpler.
>

I feel it is simpler other way around especially if I am testing and
seeing failures but I see genpd succeeding. That's confusing.

--
Regards,
Sudeep

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 10/14] cpuidle: psci: Prepare to use OS initiated suspend mode via PM domains
  2019-12-19 18:01         ` Sudeep Holla
@ 2019-12-19 21:33           ` Ulf Hansson
  -1 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-19 21:33 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: Lorenzo Pieralisi, Rob Herring, Linux PM, Rafael J . Wysocki,
	Daniel Lezcano, Mark Rutland, Lina Iyer, Vincent Guittot,
	Stephen Boyd, Andy Gross, Bjorn Andersson, Kevin Hilman,
	Linux ARM, linux-arm-msm

On Thu, 19 Dec 2019 at 19:01, Sudeep Holla <sudeep.holla@arm.com> wrote:
>
> On Thu, Dec 19, 2019 at 04:48:13PM +0100, Ulf Hansson wrote:
> > On Thu, 19 Dec 2019 at 15:32, Sudeep Holla <sudeep.holla@arm.com> wrote:
> > >
> > > On Wed, Dec 11, 2019 at 04:43:39PM +0100, Ulf Hansson wrote:
> > > > The per CPU variable psci_power_state, contains an array of fixed values,
> > > > which reflects the corresponding arm,psci-suspend-param parsed from DT, for
> > > > each of the available CPU idle states.
> > > >
> > > > This isn't sufficient when using the hierarchical CPU topology in DT, in
> > > > combination with having PSCI OS initiated (OSI) mode enabled. More
> > > > precisely, in OSI mode, Linux is responsible of telling the PSCI FW what
> > > > idle state the cluster (a group of CPUs) should enter, while in PSCI
> > > > Platform Coordinated (PC) mode, each CPU independently votes for an idle
> > > > state of the cluster.
> > > >
> > > > For this reason, introduce a per CPU variable called domain_state and
> > > > implement two helper functions to read/write its value. Then let the
> > > > domain_state take precedence over the regular selected state, when entering
> > > > and idle state.
> > > >
> > > > To avoid executing the above OSI specific code in the ->enter() callback,
> > > > while operating in the default PSCI Platform Coordinated mode, let's also
> > > > add a new enter-function and use it for OSI.
> > > >
> > > > Co-developed-by: Lina Iyer <lina.iyer@linaro.org>
> > > > Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
> > > > Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> > > > ---
> > > >
> > > > Changes in v4:
> > > >       - Rebased on top of earlier changes.
> > > >       - Add comment about using the deepest cpuidle state for the domain state
> > > >       selection.
> > > >
> > > > ---
> > > >  drivers/cpuidle/cpuidle-psci.c | 56 ++++++++++++++++++++++++++++++----
> > > >  1 file changed, 50 insertions(+), 6 deletions(-)
> > > >
> > > > diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c
> > > > index 6a87848be3c3..9600fe674a89 100644
> > > > --- a/drivers/cpuidle/cpuidle-psci.c
> > > > +++ b/drivers/cpuidle/cpuidle-psci.c
> > > > @@ -29,14 +29,47 @@ struct psci_cpuidle_data {
> > > >  };
> > > >
> > > >  static DEFINE_PER_CPU_READ_MOSTLY(struct psci_cpuidle_data, psci_cpuidle_data);
> > > > +static DEFINE_PER_CPU(u32, domain_state);
> > > > +
> > >
> > > [...]
> > >
> > > > +static int psci_enter_domain_idle_state(struct cpuidle_device *dev,
> > > > +                                     struct cpuidle_driver *drv, int idx)
> > > > +{
> > > > +     struct psci_cpuidle_data *data = this_cpu_ptr(&psci_cpuidle_data);
> > > > +     u32 *states = data->psci_states;
> > >
> > > Why can't the above be like this for consistency(see below in
> > > psci_enter_idle_state) ?
> >
> > You have a point, however in patch11 I am adding this line below.
> >
> > struct device *pd_dev = data->dev;
> >
> > So I don't think it matters much, agree?
> >
>
> Ah OK, looked odd as part of this patch, may be you could have moved
> this change into that patch. Anyways fine as is.

Okay, then I rather just keep it.

>
> > >
> > >         u32 *states = __this_cpu_read(psci_cpuidle_data.psci_states);
> > >
> > > > +     u32 state = psci_get_domain_state();
> > > > +     int ret;
> > > > +
> > > > +     if (!state)
> > > > +             state = states[idx];
> > > > +
> > > > +     ret = psci_enter_state(idx, state);
> > > > +
> > > > +     /* Clear the domain state to start fresh when back from idle. */
> > > > +     psci_set_domain_state(0);
> > > > +     return ret;
> > > > +}
> > > >
> > >
> > > [...]
> > >
> > > > @@ -118,6 +152,15 @@ static int __init psci_dt_cpu_init_idle(struct device_node *cpu_node,
> > > >                       ret = PTR_ERR(data->dev);
> > > >                       goto free_mem;
> > > >               }
> > > > +
> > > > +             /*
> > > > +              * Using the deepest state for the CPU to trigger a potential
> > > > +              * selection of a shared state for the domain, assumes the
> > > > +              * domain states are all deeper states.
> > > > +              */
> > > > +             if (data->dev)
> > >
> > > You can drop this check as return on error above.
> >
> > Actually not, because if OSI is supported, there is still a
> > possibility that the PM domain topology isn't used.
> >
>
> And how do we support that ? I am missing something here.
>
> > This means ->data->dev is NULL.
> >
>
> I don't get that.

This is quite similar to the existing limited support we have for OSI today.

We are using the idle states for the CPU, but ignoring the idle states
for the cluster. If you just skip applying the DTS patch14, this is
what happens.

>
> > >
> > > > +                     drv->states[state_count - 1].enter =
> > > > +                             psci_enter_domain_idle_state;
> > >
> > > I see the comment above but this potential blocks retention mode at
> > > cluster level when all cpu enter retention at CPU level. I don't like
> > > this assumption, but I don't have any better suggestion. Please add the
> > > note that we can't enter RETENTION state at cluster/domain level when
> > > all CPUs enter at CPU level.
> >
> > You are correct, but I think the comment a few lines above (agreed to
> > be added by Lorenzo in the previous version) should be enough to
> > explain that. No?
> >
> > The point is, this is only a problem if cluster RETENTION is
> > considered to be a shallower state that CPU power off, for example.
> >
>
> Yes, but give examples makes it better and helps people who may be
> wondering why cluster retention state is not being entered. You can just
> add to the above comment:
>
> "e.g. If CPU Retention is one of the shallower state, then we can't enter
> any of the allowed domain states."

Hmm, that it's not a correct statement I think, let me elaborate.

The problem is, that in case the CPU has both RETENTION and POWER OFF
(deepest CPU state), we would only be able to reach a cluster state
(RETENTION or POWER OFF) when the CPUs are in CPU POWER OFF (as that's
the deepest).

This is okay, as long as a cluster RETENTION state is considered being
"deeper" than the CPU POWER OFF state. However, if that isn't the
case, it means  the cluster RETENTION state is not considered in the
correct order, but it's still possible to reach as a "domain state".

I think this all is kind of summarized in the comment I agreed upon
with Lorenzo, but if you still think there is some clarification
needed I happy to add it.

Makes sense?

[...]

Kind regards
Uffe

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 10/14] cpuidle: psci: Prepare to use OS initiated suspend mode via PM domains
@ 2019-12-19 21:33           ` Ulf Hansson
  0 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-19 21:33 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: Mark Rutland, Lorenzo Pieralisi, Linux PM, Stephen Boyd,
	linux-arm-msm, Daniel Lezcano, Rafael J . Wysocki, Andy Gross,
	Lina Iyer, Bjorn Andersson, Kevin Hilman, Rob Herring, Linux ARM

On Thu, 19 Dec 2019 at 19:01, Sudeep Holla <sudeep.holla@arm.com> wrote:
>
> On Thu, Dec 19, 2019 at 04:48:13PM +0100, Ulf Hansson wrote:
> > On Thu, 19 Dec 2019 at 15:32, Sudeep Holla <sudeep.holla@arm.com> wrote:
> > >
> > > On Wed, Dec 11, 2019 at 04:43:39PM +0100, Ulf Hansson wrote:
> > > > The per CPU variable psci_power_state, contains an array of fixed values,
> > > > which reflects the corresponding arm,psci-suspend-param parsed from DT, for
> > > > each of the available CPU idle states.
> > > >
> > > > This isn't sufficient when using the hierarchical CPU topology in DT, in
> > > > combination with having PSCI OS initiated (OSI) mode enabled. More
> > > > precisely, in OSI mode, Linux is responsible of telling the PSCI FW what
> > > > idle state the cluster (a group of CPUs) should enter, while in PSCI
> > > > Platform Coordinated (PC) mode, each CPU independently votes for an idle
> > > > state of the cluster.
> > > >
> > > > For this reason, introduce a per CPU variable called domain_state and
> > > > implement two helper functions to read/write its value. Then let the
> > > > domain_state take precedence over the regular selected state, when entering
> > > > and idle state.
> > > >
> > > > To avoid executing the above OSI specific code in the ->enter() callback,
> > > > while operating in the default PSCI Platform Coordinated mode, let's also
> > > > add a new enter-function and use it for OSI.
> > > >
> > > > Co-developed-by: Lina Iyer <lina.iyer@linaro.org>
> > > > Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
> > > > Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> > > > ---
> > > >
> > > > Changes in v4:
> > > >       - Rebased on top of earlier changes.
> > > >       - Add comment about using the deepest cpuidle state for the domain state
> > > >       selection.
> > > >
> > > > ---
> > > >  drivers/cpuidle/cpuidle-psci.c | 56 ++++++++++++++++++++++++++++++----
> > > >  1 file changed, 50 insertions(+), 6 deletions(-)
> > > >
> > > > diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c
> > > > index 6a87848be3c3..9600fe674a89 100644
> > > > --- a/drivers/cpuidle/cpuidle-psci.c
> > > > +++ b/drivers/cpuidle/cpuidle-psci.c
> > > > @@ -29,14 +29,47 @@ struct psci_cpuidle_data {
> > > >  };
> > > >
> > > >  static DEFINE_PER_CPU_READ_MOSTLY(struct psci_cpuidle_data, psci_cpuidle_data);
> > > > +static DEFINE_PER_CPU(u32, domain_state);
> > > > +
> > >
> > > [...]
> > >
> > > > +static int psci_enter_domain_idle_state(struct cpuidle_device *dev,
> > > > +                                     struct cpuidle_driver *drv, int idx)
> > > > +{
> > > > +     struct psci_cpuidle_data *data = this_cpu_ptr(&psci_cpuidle_data);
> > > > +     u32 *states = data->psci_states;
> > >
> > > Why can't the above be like this for consistency(see below in
> > > psci_enter_idle_state) ?
> >
> > You have a point, however in patch11 I am adding this line below.
> >
> > struct device *pd_dev = data->dev;
> >
> > So I don't think it matters much, agree?
> >
>
> Ah OK, looked odd as part of this patch, may be you could have moved
> this change into that patch. Anyways fine as is.

Okay, then I rather just keep it.

>
> > >
> > >         u32 *states = __this_cpu_read(psci_cpuidle_data.psci_states);
> > >
> > > > +     u32 state = psci_get_domain_state();
> > > > +     int ret;
> > > > +
> > > > +     if (!state)
> > > > +             state = states[idx];
> > > > +
> > > > +     ret = psci_enter_state(idx, state);
> > > > +
> > > > +     /* Clear the domain state to start fresh when back from idle. */
> > > > +     psci_set_domain_state(0);
> > > > +     return ret;
> > > > +}
> > > >
> > >
> > > [...]
> > >
> > > > @@ -118,6 +152,15 @@ static int __init psci_dt_cpu_init_idle(struct device_node *cpu_node,
> > > >                       ret = PTR_ERR(data->dev);
> > > >                       goto free_mem;
> > > >               }
> > > > +
> > > > +             /*
> > > > +              * Using the deepest state for the CPU to trigger a potential
> > > > +              * selection of a shared state for the domain, assumes the
> > > > +              * domain states are all deeper states.
> > > > +              */
> > > > +             if (data->dev)
> > >
> > > You can drop this check as return on error above.
> >
> > Actually not, because if OSI is supported, there is still a
> > possibility that the PM domain topology isn't used.
> >
>
> And how do we support that ? I am missing something here.
>
> > This means ->data->dev is NULL.
> >
>
> I don't get that.

This is quite similar to the existing limited support we have for OSI today.

We are using the idle states for the CPU, but ignoring the idle states
for the cluster. If you just skip applying the DTS patch14, this is
what happens.

>
> > >
> > > > +                     drv->states[state_count - 1].enter =
> > > > +                             psci_enter_domain_idle_state;
> > >
> > > I see the comment above but this potential blocks retention mode at
> > > cluster level when all cpu enter retention at CPU level. I don't like
> > > this assumption, but I don't have any better suggestion. Please add the
> > > note that we can't enter RETENTION state at cluster/domain level when
> > > all CPUs enter at CPU level.
> >
> > You are correct, but I think the comment a few lines above (agreed to
> > be added by Lorenzo in the previous version) should be enough to
> > explain that. No?
> >
> > The point is, this is only a problem if cluster RETENTION is
> > considered to be a shallower state that CPU power off, for example.
> >
>
> Yes, but give examples makes it better and helps people who may be
> wondering why cluster retention state is not being entered. You can just
> add to the above comment:
>
> "e.g. If CPU Retention is one of the shallower state, then we can't enter
> any of the allowed domain states."

Hmm, that it's not a correct statement I think, let me elaborate.

The problem is, that in case the CPU has both RETENTION and POWER OFF
(deepest CPU state), we would only be able to reach a cluster state
(RETENTION or POWER OFF) when the CPUs are in CPU POWER OFF (as that's
the deepest).

This is okay, as long as a cluster RETENTION state is considered being
"deeper" than the CPU POWER OFF state. However, if that isn't the
case, it means  the cluster RETENTION state is not considered in the
correct order, but it's still possible to reach as a "domain state".

I think this all is kind of summarized in the comment I agreed upon
with Lorenzo, but if you still think there is some clarification
needed I happy to add it.

Makes sense?

[...]

Kind regards
Uffe

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 13/14] cpuidle: psci: Add support for PM domains by using genpd
  2019-12-19 18:06         ` Sudeep Holla
@ 2019-12-19 22:02           ` Ulf Hansson
  -1 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-19 22:02 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: Lorenzo Pieralisi, Rob Herring, Linux PM, Rafael J . Wysocki,
	Daniel Lezcano, Mark Rutland, Lina Iyer, Vincent Guittot,
	Stephen Boyd, Andy Gross, Bjorn Andersson, Kevin Hilman,
	Linux ARM, linux-arm-msm

On Thu, 19 Dec 2019 at 19:06, Sudeep Holla <sudeep.holla@arm.com> wrote:
>
> On Thu, Dec 19, 2019 at 04:48:39PM +0100, Ulf Hansson wrote:
> > On Thu, 19 Dec 2019 at 15:34, Sudeep Holla <sudeep.holla@arm.com> wrote:
> > >
> > > On Wed, Dec 11, 2019 at 04:43:42PM +0100, Ulf Hansson wrote:
> > > > When the hierarchical CPU topology layout is used in DT and the PSCI OSI
> > > > mode is supported by the PSCI FW, let's initialize a corresponding PM
> > > > domain topology by using genpd. This enables a CPU and a group of CPUs,
> > > > when attached to the topology, to be power-managed accordingly.
> > > >
> > > > To trigger the attempt to initialize the genpd data structures let's use a
> > > > subsys_initcall, which should be early enough to allow CPUs, but also other
> > > > devices to be attached.
> > > >
> > > > The initialization consists of parsing the PSCI OF node for the topology
> > > > and the "domain idle states" DT bindings. In case the idle states are
> > > > compatible with "domain-idle-state", the initialized genpd becomes
> > > > responsible of selecting an idle state for the PM domain, via assigning it
> > > > a genpd governor.
> > > >
> > > > Note that, a successful initialization of the genpd data structures, is
> > > > followed by a call to psci_set_osi_mode(), as to try to enable the OSI mode
> > > > in the PSCI FW. In case this fails, we fall back into a degraded mode
> > > > rather than bailing out and returning an error code.
> > > >
> > > > Co-developed-by: Lina Iyer <lina.iyer@linaro.org>
> > > > Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
> > > > Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> > > > ---
> > > >
> > > > Changes in v4:
> > > >       - None.
> > > >
> > > > ---
> > > >  drivers/cpuidle/cpuidle-psci-domain.c | 267 ++++++++++++++++++++++++++
> > > >  drivers/cpuidle/cpuidle-psci.c        |   4 +-
> > > >  drivers/cpuidle/cpuidle-psci.h        |   5 +
> > > >  3 files changed, 274 insertions(+), 2 deletions(-)
> > > >
> > > > diff --git a/drivers/cpuidle/cpuidle-psci-domain.c b/drivers/cpuidle/cpuidle-psci-domain.c
> > > > index 656ef3d59149..c2f94ba42222 100644
> > > > --- a/drivers/cpuidle/cpuidle-psci-domain.c
> > > > +++ b/drivers/cpuidle/cpuidle-psci-domain.c
> > > > @@ -7,14 +7,281 @@
> > > >   *
> > > >   */
> > > >
> > > > +#define pr_fmt(fmt) "CPUidle PSCI: " fmt
> > > > +
> > > >  #include <linux/cpu.h>
> > > >  #include <linux/device.h>
> > > >  #include <linux/kernel.h>
> > > >  #include <linux/pm_domain.h>
> > > >  #include <linux/pm_runtime.h>
> > > > +#include <linux/psci.h>
> > > > +#include <linux/slab.h>
> > > > +#include <linux/string.h>
> > > >
> > > >  #include "cpuidle-psci.h"
> > > >
> > > > +struct psci_pd_provider {
> > > > +     struct list_head link;
> > > > +     struct device_node *node;
> > > > +};
> > > > +
> > > > +static LIST_HEAD(psci_pd_providers);
> > > > +static bool osi_mode_enabled;
> > > > +
> > > > +static int psci_pd_power_off(struct generic_pm_domain *pd)
> > > > +{
> > > > +     struct genpd_power_state *state = &pd->states[pd->state_idx];
> > > > +     u32 *pd_state;
> > > > +
> > > > +     /* If we have failed to enable OSI mode, then abort power off. */
> > > > +     if (!osi_mode_enabled)
> > > > +             return -EBUSY;
> > > > +
> > >
> > > Why is above check needed ? Shouldn't we have disable/remove pd of
> > > OSI is not enabled ?
> >
> > Well, failing to enable OSI should in practice not happen, while it
> > theoretically it could.
> >
>
> I won't assume that. Since it's new and not tested yet, I prefer to assume
> it can fail.

Yes, I agree. Hence the degraded mode.

>
> > My approach to this has been to fall back to use a "degraded mode",
> > which seems quite common for these kind of situations. The degraded
> > mode means, we are preventing domain states from being used.
> >
>
> But why can't we just fail registering or remove if already added.

We can, but there are more problems with that than leaving this in a
degraded mode, I think. See more below.

> They are useless for "degraded mode" anyways. And it will ensure that
> data->dev is NULL. Sorry now I see why you said it can be NULL but I
> would rather not leave those unused genpd in place in case of error.

data->dev would not be NULL in this case, because the
dev_pm_domain_attach_by_name() which is called when we attach the CPU
is going to return an error code, not NULL.

That's because the connection is there in the DTB and thus it must
fail, in this case it would be with -EPROBE_DEFER (waiting for a genpd
provider to be registered).

That would then lead to that the entire cpuidle-psci driver would fail
to initiate/probe. In my opinion, I think it's better to fall back
into a degraded mode, using all the idle states for the CPUs, but just
preventing the cluster idle states.

Just wanted to make this more clear for you to consider. I am happy to
change in any way you suggest, but please confirm that you really want
another behaviour than the degraded mode.

>
> > More importantly, it also keeps the code registering the PM domains, a
> > bit simpler.
> >
>
> I feel it is simpler other way around especially if I am testing and
> seeing failures but I see genpd succeeding. That's confusing.

There is an warning message printed if psci_set_osi_mode() fails,
"failed to enable OSI mode", in psci_idle_init_domains().

We could potentially add some more information to that message, that
this also leads into using a "degraded mode". Would that be sufficient
to satisfy your concerns?

Kind regards
Uffe

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 13/14] cpuidle: psci: Add support for PM domains by using genpd
@ 2019-12-19 22:02           ` Ulf Hansson
  0 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-19 22:02 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: Mark Rutland, Lorenzo Pieralisi, Linux PM, Stephen Boyd,
	linux-arm-msm, Daniel Lezcano, Rafael J . Wysocki, Andy Gross,
	Lina Iyer, Bjorn Andersson, Kevin Hilman, Rob Herring, Linux ARM

On Thu, 19 Dec 2019 at 19:06, Sudeep Holla <sudeep.holla@arm.com> wrote:
>
> On Thu, Dec 19, 2019 at 04:48:39PM +0100, Ulf Hansson wrote:
> > On Thu, 19 Dec 2019 at 15:34, Sudeep Holla <sudeep.holla@arm.com> wrote:
> > >
> > > On Wed, Dec 11, 2019 at 04:43:42PM +0100, Ulf Hansson wrote:
> > > > When the hierarchical CPU topology layout is used in DT and the PSCI OSI
> > > > mode is supported by the PSCI FW, let's initialize a corresponding PM
> > > > domain topology by using genpd. This enables a CPU and a group of CPUs,
> > > > when attached to the topology, to be power-managed accordingly.
> > > >
> > > > To trigger the attempt to initialize the genpd data structures let's use a
> > > > subsys_initcall, which should be early enough to allow CPUs, but also other
> > > > devices to be attached.
> > > >
> > > > The initialization consists of parsing the PSCI OF node for the topology
> > > > and the "domain idle states" DT bindings. In case the idle states are
> > > > compatible with "domain-idle-state", the initialized genpd becomes
> > > > responsible of selecting an idle state for the PM domain, via assigning it
> > > > a genpd governor.
> > > >
> > > > Note that, a successful initialization of the genpd data structures, is
> > > > followed by a call to psci_set_osi_mode(), as to try to enable the OSI mode
> > > > in the PSCI FW. In case this fails, we fall back into a degraded mode
> > > > rather than bailing out and returning an error code.
> > > >
> > > > Co-developed-by: Lina Iyer <lina.iyer@linaro.org>
> > > > Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
> > > > Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> > > > ---
> > > >
> > > > Changes in v4:
> > > >       - None.
> > > >
> > > > ---
> > > >  drivers/cpuidle/cpuidle-psci-domain.c | 267 ++++++++++++++++++++++++++
> > > >  drivers/cpuidle/cpuidle-psci.c        |   4 +-
> > > >  drivers/cpuidle/cpuidle-psci.h        |   5 +
> > > >  3 files changed, 274 insertions(+), 2 deletions(-)
> > > >
> > > > diff --git a/drivers/cpuidle/cpuidle-psci-domain.c b/drivers/cpuidle/cpuidle-psci-domain.c
> > > > index 656ef3d59149..c2f94ba42222 100644
> > > > --- a/drivers/cpuidle/cpuidle-psci-domain.c
> > > > +++ b/drivers/cpuidle/cpuidle-psci-domain.c
> > > > @@ -7,14 +7,281 @@
> > > >   *
> > > >   */
> > > >
> > > > +#define pr_fmt(fmt) "CPUidle PSCI: " fmt
> > > > +
> > > >  #include <linux/cpu.h>
> > > >  #include <linux/device.h>
> > > >  #include <linux/kernel.h>
> > > >  #include <linux/pm_domain.h>
> > > >  #include <linux/pm_runtime.h>
> > > > +#include <linux/psci.h>
> > > > +#include <linux/slab.h>
> > > > +#include <linux/string.h>
> > > >
> > > >  #include "cpuidle-psci.h"
> > > >
> > > > +struct psci_pd_provider {
> > > > +     struct list_head link;
> > > > +     struct device_node *node;
> > > > +};
> > > > +
> > > > +static LIST_HEAD(psci_pd_providers);
> > > > +static bool osi_mode_enabled;
> > > > +
> > > > +static int psci_pd_power_off(struct generic_pm_domain *pd)
> > > > +{
> > > > +     struct genpd_power_state *state = &pd->states[pd->state_idx];
> > > > +     u32 *pd_state;
> > > > +
> > > > +     /* If we have failed to enable OSI mode, then abort power off. */
> > > > +     if (!osi_mode_enabled)
> > > > +             return -EBUSY;
> > > > +
> > >
> > > Why is above check needed ? Shouldn't we have disable/remove pd of
> > > OSI is not enabled ?
> >
> > Well, failing to enable OSI should in practice not happen, while it
> > theoretically it could.
> >
>
> I won't assume that. Since it's new and not tested yet, I prefer to assume
> it can fail.

Yes, I agree. Hence the degraded mode.

>
> > My approach to this has been to fall back to use a "degraded mode",
> > which seems quite common for these kind of situations. The degraded
> > mode means, we are preventing domain states from being used.
> >
>
> But why can't we just fail registering or remove if already added.

We can, but there are more problems with that than leaving this in a
degraded mode, I think. See more below.

> They are useless for "degraded mode" anyways. And it will ensure that
> data->dev is NULL. Sorry now I see why you said it can be NULL but I
> would rather not leave those unused genpd in place in case of error.

data->dev would not be NULL in this case, because the
dev_pm_domain_attach_by_name() which is called when we attach the CPU
is going to return an error code, not NULL.

That's because the connection is there in the DTB and thus it must
fail, in this case it would be with -EPROBE_DEFER (waiting for a genpd
provider to be registered).

That would then lead to that the entire cpuidle-psci driver would fail
to initiate/probe. In my opinion, I think it's better to fall back
into a degraded mode, using all the idle states for the CPUs, but just
preventing the cluster idle states.

Just wanted to make this more clear for you to consider. I am happy to
change in any way you suggest, but please confirm that you really want
another behaviour than the degraded mode.

>
> > More importantly, it also keeps the code registering the PM domains, a
> > bit simpler.
> >
>
> I feel it is simpler other way around especially if I am testing and
> seeing failures but I see genpd succeeding. That's confusing.

There is an warning message printed if psci_set_osi_mode() fails,
"failed to enable OSI mode", in psci_idle_init_domains().

We could potentially add some more information to that message, that
this also leads into using a "degraded mode". Would that be sufficient
to satisfy your concerns?

Kind regards
Uffe

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 10/14] cpuidle: psci: Prepare to use OS initiated suspend mode via PM domains
  2019-12-19 21:33           ` Ulf Hansson
@ 2019-12-20 10:01             ` Sudeep Holla
  -1 siblings, 0 replies; 76+ messages in thread
From: Sudeep Holla @ 2019-12-20 10:01 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Lorenzo Pieralisi, Rob Herring, Linux PM, Rafael J . Wysocki,
	Daniel Lezcano, Mark Rutland, Lina Iyer, Vincent Guittot,
	Stephen Boyd, Andy Gross, Bjorn Andersson, Kevin Hilman,
	Linux ARM, Sudeep Holla, linux-arm-msm

On Thu, Dec 19, 2019 at 10:33:34PM +0100, Ulf Hansson wrote:
> On Thu, 19 Dec 2019 at 19:01, Sudeep Holla <sudeep.holla@arm.com> wrote:
> >
> > On Thu, Dec 19, 2019 at 04:48:13PM +0100, Ulf Hansson wrote:
> > > On Thu, 19 Dec 2019 at 15:32, Sudeep Holla <sudeep.holla@arm.com> wrote:
> > > >
> > > > On Wed, Dec 11, 2019 at 04:43:39PM +0100, Ulf Hansson wrote:
> > > > > The per CPU variable psci_power_state, contains an array of fixed values,
> > > > > which reflects the corresponding arm,psci-suspend-param parsed from DT, for
> > > > > each of the available CPU idle states.
> > > > >
> > > > > This isn't sufficient when using the hierarchical CPU topology in DT, in
> > > > > combination with having PSCI OS initiated (OSI) mode enabled. More
> > > > > precisely, in OSI mode, Linux is responsible of telling the PSCI FW what
> > > > > idle state the cluster (a group of CPUs) should enter, while in PSCI
> > > > > Platform Coordinated (PC) mode, each CPU independently votes for an idle
> > > > > state of the cluster.
> > > > >
> > > > > For this reason, introduce a per CPU variable called domain_state and
> > > > > implement two helper functions to read/write its value. Then let the
> > > > > domain_state take precedence over the regular selected state, when entering
> > > > > and idle state.
> > > > >
> > > > > To avoid executing the above OSI specific code in the ->enter() callback,
> > > > > while operating in the default PSCI Platform Coordinated mode, let's also
> > > > > add a new enter-function and use it for OSI.
> > > > >
> > > > > Co-developed-by: Lina Iyer <lina.iyer@linaro.org>
> > > > > Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
> > > > > Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> > > > > ---
> > > > >
> > > > > Changes in v4:
> > > > >       - Rebased on top of earlier changes.
> > > > >       - Add comment about using the deepest cpuidle state for the domain state
> > > > >       selection.
> > > > >
> > > > > ---
> > > > >  drivers/cpuidle/cpuidle-psci.c | 56 ++++++++++++++++++++++++++++++----
> > > > >  1 file changed, 50 insertions(+), 6 deletions(-)
> > > > >
> > > > > diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c
> > > > > index 6a87848be3c3..9600fe674a89 100644
> > > > > --- a/drivers/cpuidle/cpuidle-psci.c
> > > > > +++ b/drivers/cpuidle/cpuidle-psci.c
> > > > > @@ -29,14 +29,47 @@ struct psci_cpuidle_data {
> > > > >  };
> > > > >
> > > > >  static DEFINE_PER_CPU_READ_MOSTLY(struct psci_cpuidle_data, psci_cpuidle_data);
> > > > > +static DEFINE_PER_CPU(u32, domain_state);
> > > > > +
> > > >
> > > > [...]
> > > >
> > > > > +static int psci_enter_domain_idle_state(struct cpuidle_device *dev,
> > > > > +                                     struct cpuidle_driver *drv, int idx)
> > > > > +{
> > > > > +     struct psci_cpuidle_data *data = this_cpu_ptr(&psci_cpuidle_data);
> > > > > +     u32 *states = data->psci_states;
> > > >
> > > > Why can't the above be like this for consistency(see below in
> > > > psci_enter_idle_state) ?
> > >
> > > You have a point, however in patch11 I am adding this line below.
> > >
> > > struct device *pd_dev = data->dev;
> > >
> > > So I don't think it matters much, agree?
> > >
> >
> > Ah OK, looked odd as part of this patch, may be you could have moved
> > this change into that patch. Anyways fine as is.
>
> Okay, then I rather just keep it.
>
> >
> > > >
> > > >         u32 *states = __this_cpu_read(psci_cpuidle_data.psci_states);
> > > >
> > > > > +     u32 state = psci_get_domain_state();
> > > > > +     int ret;
> > > > > +
> > > > > +     if (!state)
> > > > > +             state = states[idx];
> > > > > +
> > > > > +     ret = psci_enter_state(idx, state);
> > > > > +
> > > > > +     /* Clear the domain state to start fresh when back from idle. */
> > > > > +     psci_set_domain_state(0);
> > > > > +     return ret;
> > > > > +}
> > > > >
> > > >
> > > > [...]
> > > >
> > > > > @@ -118,6 +152,15 @@ static int __init psci_dt_cpu_init_idle(struct device_node *cpu_node,
> > > > >                       ret = PTR_ERR(data->dev);
> > > > >                       goto free_mem;
> > > > >               }
> > > > > +
> > > > > +             /*
> > > > > +              * Using the deepest state for the CPU to trigger a potential
> > > > > +              * selection of a shared state for the domain, assumes the
> > > > > +              * domain states are all deeper states.
> > > > > +              */
> > > > > +             if (data->dev)
> > > >
> > > > You can drop this check as return on error above.
> > >
> > > Actually not, because if OSI is supported, there is still a
> > > possibility that the PM domain topology isn't used.
> > >
> >
> > And how do we support that ? I am missing something here.
> >
> > > This means ->data->dev is NULL.
> > >
> >
> > I don't get that.
>
> This is quite similar to the existing limited support we have for OSI today.
>
> We are using the idle states for the CPU, but ignoring the idle states
> for the cluster. If you just skip applying the DTS patch14, this is
> what happens.
>

No if psci_set_osi fails, we shouldn't create genpd domain as we don't
enter any cluster state. The default mode(same as PC) should work which
don't need any genpd domains. Adding one which is unused is just confusion.
Please avoid that.

> >
> > > >
> > > > > +                     drv->states[state_count - 1].enter =
> > > > > +                             psci_enter_domain_idle_state;
> > > >
> > > > I see the comment above but this potential blocks retention mode at
> > > > cluster level when all cpu enter retention at CPU level. I don't like
> > > > this assumption, but I don't have any better suggestion. Please add the
> > > > note that we can't enter RETENTION state at cluster/domain level when
> > > > all CPUs enter at CPU level.
> > >
> > > You are correct, but I think the comment a few lines above (agreed to
> > > be added by Lorenzo in the previous version) should be enough to
> > > explain that. No?
> > >
> > > The point is, this is only a problem if cluster RETENTION is
> > > considered to be a shallower state that CPU power off, for example.
> > >
> >
> > Yes, but give examples makes it better and helps people who may be
> > wondering why cluster retention state is not being entered. You can just
> > add to the above comment:
> >
> > "e.g. If CPU Retention is one of the shallower state, then we can't enter
> > any of the allowed domain states."
>
> Hmm, that it's not a correct statement I think, let me elaborate.
>
> The problem is, that in case the CPU has both RETENTION and POWER OFF
> (deepest CPU state), we would only be able to reach a cluster state
> (RETENTION or POWER OFF) when the CPUs are in CPU POWER OFF (as that's
> the deepest).
>

Sorry for the poor choice of words. What I meant is only one can be
deepest and it will be CPU POWER OFF if it exist at the CPU level.
RETENTION(again if exist) is shallower(rather deeper but not deepest
state).

> This is okay, as long as a cluster RETENTION state is considered being
> "deeper" than the CPU POWER OFF state. However, if that isn't the
> case, it means  the cluster RETENTION state is not considered in the
> correct order, but it's still possible to reach as a "domain state".
>

Again sorry for not being clear, I was referring CPU RET + CLUSTER RET.

> I think this all is kind of summarized in the comment I agreed upon
> with Lorenzo, but if you still think there is some clarification
> needed I happy to add it.
>
> Makes sense?
>

OK, if you happy, that's fine. I just wanted to clearly state CPU RET
+ CLUSTER RET is not possible with the implementation.

--
Regards,
Sudeep

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 10/14] cpuidle: psci: Prepare to use OS initiated suspend mode via PM domains
@ 2019-12-20 10:01             ` Sudeep Holla
  0 siblings, 0 replies; 76+ messages in thread
From: Sudeep Holla @ 2019-12-20 10:01 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Mark Rutland, Lorenzo Pieralisi, Linux PM, Stephen Boyd,
	linux-arm-msm, Daniel Lezcano, Rafael J . Wysocki, Andy Gross,
	Lina Iyer, Bjorn Andersson, Kevin Hilman, Rob Herring,
	Sudeep Holla, Linux ARM

On Thu, Dec 19, 2019 at 10:33:34PM +0100, Ulf Hansson wrote:
> On Thu, 19 Dec 2019 at 19:01, Sudeep Holla <sudeep.holla@arm.com> wrote:
> >
> > On Thu, Dec 19, 2019 at 04:48:13PM +0100, Ulf Hansson wrote:
> > > On Thu, 19 Dec 2019 at 15:32, Sudeep Holla <sudeep.holla@arm.com> wrote:
> > > >
> > > > On Wed, Dec 11, 2019 at 04:43:39PM +0100, Ulf Hansson wrote:
> > > > > The per CPU variable psci_power_state, contains an array of fixed values,
> > > > > which reflects the corresponding arm,psci-suspend-param parsed from DT, for
> > > > > each of the available CPU idle states.
> > > > >
> > > > > This isn't sufficient when using the hierarchical CPU topology in DT, in
> > > > > combination with having PSCI OS initiated (OSI) mode enabled. More
> > > > > precisely, in OSI mode, Linux is responsible of telling the PSCI FW what
> > > > > idle state the cluster (a group of CPUs) should enter, while in PSCI
> > > > > Platform Coordinated (PC) mode, each CPU independently votes for an idle
> > > > > state of the cluster.
> > > > >
> > > > > For this reason, introduce a per CPU variable called domain_state and
> > > > > implement two helper functions to read/write its value. Then let the
> > > > > domain_state take precedence over the regular selected state, when entering
> > > > > and idle state.
> > > > >
> > > > > To avoid executing the above OSI specific code in the ->enter() callback,
> > > > > while operating in the default PSCI Platform Coordinated mode, let's also
> > > > > add a new enter-function and use it for OSI.
> > > > >
> > > > > Co-developed-by: Lina Iyer <lina.iyer@linaro.org>
> > > > > Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
> > > > > Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> > > > > ---
> > > > >
> > > > > Changes in v4:
> > > > >       - Rebased on top of earlier changes.
> > > > >       - Add comment about using the deepest cpuidle state for the domain state
> > > > >       selection.
> > > > >
> > > > > ---
> > > > >  drivers/cpuidle/cpuidle-psci.c | 56 ++++++++++++++++++++++++++++++----
> > > > >  1 file changed, 50 insertions(+), 6 deletions(-)
> > > > >
> > > > > diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c
> > > > > index 6a87848be3c3..9600fe674a89 100644
> > > > > --- a/drivers/cpuidle/cpuidle-psci.c
> > > > > +++ b/drivers/cpuidle/cpuidle-psci.c
> > > > > @@ -29,14 +29,47 @@ struct psci_cpuidle_data {
> > > > >  };
> > > > >
> > > > >  static DEFINE_PER_CPU_READ_MOSTLY(struct psci_cpuidle_data, psci_cpuidle_data);
> > > > > +static DEFINE_PER_CPU(u32, domain_state);
> > > > > +
> > > >
> > > > [...]
> > > >
> > > > > +static int psci_enter_domain_idle_state(struct cpuidle_device *dev,
> > > > > +                                     struct cpuidle_driver *drv, int idx)
> > > > > +{
> > > > > +     struct psci_cpuidle_data *data = this_cpu_ptr(&psci_cpuidle_data);
> > > > > +     u32 *states = data->psci_states;
> > > >
> > > > Why can't the above be like this for consistency(see below in
> > > > psci_enter_idle_state) ?
> > >
> > > You have a point, however in patch11 I am adding this line below.
> > >
> > > struct device *pd_dev = data->dev;
> > >
> > > So I don't think it matters much, agree?
> > >
> >
> > Ah OK, looked odd as part of this patch, may be you could have moved
> > this change into that patch. Anyways fine as is.
>
> Okay, then I rather just keep it.
>
> >
> > > >
> > > >         u32 *states = __this_cpu_read(psci_cpuidle_data.psci_states);
> > > >
> > > > > +     u32 state = psci_get_domain_state();
> > > > > +     int ret;
> > > > > +
> > > > > +     if (!state)
> > > > > +             state = states[idx];
> > > > > +
> > > > > +     ret = psci_enter_state(idx, state);
> > > > > +
> > > > > +     /* Clear the domain state to start fresh when back from idle. */
> > > > > +     psci_set_domain_state(0);
> > > > > +     return ret;
> > > > > +}
> > > > >
> > > >
> > > > [...]
> > > >
> > > > > @@ -118,6 +152,15 @@ static int __init psci_dt_cpu_init_idle(struct device_node *cpu_node,
> > > > >                       ret = PTR_ERR(data->dev);
> > > > >                       goto free_mem;
> > > > >               }
> > > > > +
> > > > > +             /*
> > > > > +              * Using the deepest state for the CPU to trigger a potential
> > > > > +              * selection of a shared state for the domain, assumes the
> > > > > +              * domain states are all deeper states.
> > > > > +              */
> > > > > +             if (data->dev)
> > > >
> > > > You can drop this check as return on error above.
> > >
> > > Actually not, because if OSI is supported, there is still a
> > > possibility that the PM domain topology isn't used.
> > >
> >
> > And how do we support that ? I am missing something here.
> >
> > > This means ->data->dev is NULL.
> > >
> >
> > I don't get that.
>
> This is quite similar to the existing limited support we have for OSI today.
>
> We are using the idle states for the CPU, but ignoring the idle states
> for the cluster. If you just skip applying the DTS patch14, this is
> what happens.
>

No if psci_set_osi fails, we shouldn't create genpd domain as we don't
enter any cluster state. The default mode(same as PC) should work which
don't need any genpd domains. Adding one which is unused is just confusion.
Please avoid that.

> >
> > > >
> > > > > +                     drv->states[state_count - 1].enter =
> > > > > +                             psci_enter_domain_idle_state;
> > > >
> > > > I see the comment above but this potential blocks retention mode at
> > > > cluster level when all cpu enter retention at CPU level. I don't like
> > > > this assumption, but I don't have any better suggestion. Please add the
> > > > note that we can't enter RETENTION state at cluster/domain level when
> > > > all CPUs enter at CPU level.
> > >
> > > You are correct, but I think the comment a few lines above (agreed to
> > > be added by Lorenzo in the previous version) should be enough to
> > > explain that. No?
> > >
> > > The point is, this is only a problem if cluster RETENTION is
> > > considered to be a shallower state that CPU power off, for example.
> > >
> >
> > Yes, but give examples makes it better and helps people who may be
> > wondering why cluster retention state is not being entered. You can just
> > add to the above comment:
> >
> > "e.g. If CPU Retention is one of the shallower state, then we can't enter
> > any of the allowed domain states."
>
> Hmm, that it's not a correct statement I think, let me elaborate.
>
> The problem is, that in case the CPU has both RETENTION and POWER OFF
> (deepest CPU state), we would only be able to reach a cluster state
> (RETENTION or POWER OFF) when the CPUs are in CPU POWER OFF (as that's
> the deepest).
>

Sorry for the poor choice of words. What I meant is only one can be
deepest and it will be CPU POWER OFF if it exist at the CPU level.
RETENTION(again if exist) is shallower(rather deeper but not deepest
state).

> This is okay, as long as a cluster RETENTION state is considered being
> "deeper" than the CPU POWER OFF state. However, if that isn't the
> case, it means  the cluster RETENTION state is not considered in the
> correct order, but it's still possible to reach as a "domain state".
>

Again sorry for not being clear, I was referring CPU RET + CLUSTER RET.

> I think this all is kind of summarized in the comment I agreed upon
> with Lorenzo, but if you still think there is some clarification
> needed I happy to add it.
>
> Makes sense?
>

OK, if you happy, that's fine. I just wanted to clearly state CPU RET
+ CLUSTER RET is not possible with the implementation.

--
Regards,
Sudeep

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 13/14] cpuidle: psci: Add support for PM domains by using genpd
  2019-12-19 22:02           ` Ulf Hansson
@ 2019-12-20 10:07             ` Sudeep Holla
  -1 siblings, 0 replies; 76+ messages in thread
From: Sudeep Holla @ 2019-12-20 10:07 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Lorenzo Pieralisi, Rob Herring, Linux PM, Rafael J . Wysocki,
	Daniel Lezcano, Mark Rutland, Lina Iyer, Vincent Guittot,
	Stephen Boyd, Andy Gross, Bjorn Andersson, Kevin Hilman,
	Sudeep Holla, Linux ARM, linux-arm-msm

On Thu, Dec 19, 2019 at 11:02:40PM +0100, Ulf Hansson wrote:
> On Thu, 19 Dec 2019 at 19:06, Sudeep Holla <sudeep.holla@arm.com> wrote:
> >
> > On Thu, Dec 19, 2019 at 04:48:39PM +0100, Ulf Hansson wrote:
> > > On Thu, 19 Dec 2019 at 15:34, Sudeep Holla <sudeep.holla@arm.com> wrote:
> > > >
> > > > On Wed, Dec 11, 2019 at 04:43:42PM +0100, Ulf Hansson wrote:
> > > > > When the hierarchical CPU topology layout is used in DT and the PSCI OSI
> > > > > mode is supported by the PSCI FW, let's initialize a corresponding PM
> > > > > domain topology by using genpd. This enables a CPU and a group of CPUs,
> > > > > when attached to the topology, to be power-managed accordingly.
> > > > >
> > > > > To trigger the attempt to initialize the genpd data structures let's use a
> > > > > subsys_initcall, which should be early enough to allow CPUs, but also other
> > > > > devices to be attached.
> > > > >
> > > > > The initialization consists of parsing the PSCI OF node for the topology
> > > > > and the "domain idle states" DT bindings. In case the idle states are
> > > > > compatible with "domain-idle-state", the initialized genpd becomes
> > > > > responsible of selecting an idle state for the PM domain, via assigning it
> > > > > a genpd governor.
> > > > >
> > > > > Note that, a successful initialization of the genpd data structures, is
> > > > > followed by a call to psci_set_osi_mode(), as to try to enable the OSI mode
> > > > > in the PSCI FW. In case this fails, we fall back into a degraded mode
> > > > > rather than bailing out and returning an error code.
> > > > >
> > > > > Co-developed-by: Lina Iyer <lina.iyer@linaro.org>
> > > > > Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
> > > > > Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> > > > > ---
> > > > >
> > > > > Changes in v4:
> > > > >       - None.
> > > > >
> > > > > ---
> > > > >  drivers/cpuidle/cpuidle-psci-domain.c | 267 ++++++++++++++++++++++++++
> > > > >  drivers/cpuidle/cpuidle-psci.c        |   4 +-
> > > > >  drivers/cpuidle/cpuidle-psci.h        |   5 +
> > > > >  3 files changed, 274 insertions(+), 2 deletions(-)
> > > > >
> > > > > diff --git a/drivers/cpuidle/cpuidle-psci-domain.c b/drivers/cpuidle/cpuidle-psci-domain.c
> > > > > index 656ef3d59149..c2f94ba42222 100644
> > > > > --- a/drivers/cpuidle/cpuidle-psci-domain.c
> > > > > +++ b/drivers/cpuidle/cpuidle-psci-domain.c
> > > > > @@ -7,14 +7,281 @@
> > > > >   *
> > > > >   */
> > > > >
> > > > > +#define pr_fmt(fmt) "CPUidle PSCI: " fmt
> > > > > +
> > > > >  #include <linux/cpu.h>
> > > > >  #include <linux/device.h>
> > > > >  #include <linux/kernel.h>
> > > > >  #include <linux/pm_domain.h>
> > > > >  #include <linux/pm_runtime.h>
> > > > > +#include <linux/psci.h>
> > > > > +#include <linux/slab.h>
> > > > > +#include <linux/string.h>
> > > > >
> > > > >  #include "cpuidle-psci.h"
> > > > >
> > > > > +struct psci_pd_provider {
> > > > > +     struct list_head link;
> > > > > +     struct device_node *node;
> > > > > +};
> > > > > +
> > > > > +static LIST_HEAD(psci_pd_providers);
> > > > > +static bool osi_mode_enabled;
> > > > > +
> > > > > +static int psci_pd_power_off(struct generic_pm_domain *pd)
> > > > > +{
> > > > > +     struct genpd_power_state *state = &pd->states[pd->state_idx];
> > > > > +     u32 *pd_state;
> > > > > +
> > > > > +     /* If we have failed to enable OSI mode, then abort power off. */
> > > > > +     if (!osi_mode_enabled)
> > > > > +             return -EBUSY;
> > > > > +
> > > >
> > > > Why is above check needed ? Shouldn't we have disable/remove pd of
> > > > OSI is not enabled ?
> > >
> > > Well, failing to enable OSI should in practice not happen, while it
> > > theoretically it could.
> > >
> >
> > I won't assume that. Since it's new and not tested yet, I prefer to assume
> > it can fail.
>
> Yes, I agree. Hence the degraded mode.
>
> >
> > > My approach to this has been to fall back to use a "degraded mode",
> > > which seems quite common for these kind of situations. The degraded
> > > mode means, we are preventing domain states from being used.
> > >
> >
> > But why can't we just fail registering or remove if already added.
>
> We can, but there are more problems with that than leaving this in a
> degraded mode, I think. See more below.
>
> > They are useless for "degraded mode" anyways. And it will ensure that
> > data->dev is NULL. Sorry now I see why you said it can be NULL but I
> > would rather not leave those unused genpd in place in case of error.
>
> data->dev would not be NULL in this case, because the
> dev_pm_domain_attach_by_name() which is called when we attach the CPU
> is going to return an error code, not NULL.
>
> That's because the connection is there in the DTB and thus it must
> fail, in this case it would be with -EPROBE_DEFER (waiting for a genpd
> provider to be registered).
>
> That would then lead to that the entire cpuidle-psci driver would fail
> to initiate/probe. In my opinion, I think it's better to fall back
> into a degraded mode, using all the idle states for the CPUs, but just
> preventing the cluster idle states.
>
> Just wanted to make this more clear for you to consider. I am happy to
> change in any way you suggest, but please confirm that you really want
> another behaviour than the degraded mode.
>

Sorry but if OSI set failed in firmware, it will be operating in default/
PC mode and I *don't* want to create genpd for that. It's confusing.
Even if you don't create all these genpd domains, it is still degraded
mode and we are anyway not changing that. Let me know if my understanding
is wrong here.

I am sure, DTB may get copied to different platform and the firmware may
not support OSI. I know we have logs, but creating and leaving those
genpd domains unused will be just confusing. Please change that.

--
Regards,
Sudeep

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 13/14] cpuidle: psci: Add support for PM domains by using genpd
@ 2019-12-20 10:07             ` Sudeep Holla
  0 siblings, 0 replies; 76+ messages in thread
From: Sudeep Holla @ 2019-12-20 10:07 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Mark Rutland, Lorenzo Pieralisi, Linux PM, Stephen Boyd,
	linux-arm-msm, Daniel Lezcano, Rafael J . Wysocki, Andy Gross,
	Lina Iyer, Bjorn Andersson, Kevin Hilman, Rob Herring,
	Sudeep Holla, Linux ARM

On Thu, Dec 19, 2019 at 11:02:40PM +0100, Ulf Hansson wrote:
> On Thu, 19 Dec 2019 at 19:06, Sudeep Holla <sudeep.holla@arm.com> wrote:
> >
> > On Thu, Dec 19, 2019 at 04:48:39PM +0100, Ulf Hansson wrote:
> > > On Thu, 19 Dec 2019 at 15:34, Sudeep Holla <sudeep.holla@arm.com> wrote:
> > > >
> > > > On Wed, Dec 11, 2019 at 04:43:42PM +0100, Ulf Hansson wrote:
> > > > > When the hierarchical CPU topology layout is used in DT and the PSCI OSI
> > > > > mode is supported by the PSCI FW, let's initialize a corresponding PM
> > > > > domain topology by using genpd. This enables a CPU and a group of CPUs,
> > > > > when attached to the topology, to be power-managed accordingly.
> > > > >
> > > > > To trigger the attempt to initialize the genpd data structures let's use a
> > > > > subsys_initcall, which should be early enough to allow CPUs, but also other
> > > > > devices to be attached.
> > > > >
> > > > > The initialization consists of parsing the PSCI OF node for the topology
> > > > > and the "domain idle states" DT bindings. In case the idle states are
> > > > > compatible with "domain-idle-state", the initialized genpd becomes
> > > > > responsible of selecting an idle state for the PM domain, via assigning it
> > > > > a genpd governor.
> > > > >
> > > > > Note that, a successful initialization of the genpd data structures, is
> > > > > followed by a call to psci_set_osi_mode(), as to try to enable the OSI mode
> > > > > in the PSCI FW. In case this fails, we fall back into a degraded mode
> > > > > rather than bailing out and returning an error code.
> > > > >
> > > > > Co-developed-by: Lina Iyer <lina.iyer@linaro.org>
> > > > > Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
> > > > > Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> > > > > ---
> > > > >
> > > > > Changes in v4:
> > > > >       - None.
> > > > >
> > > > > ---
> > > > >  drivers/cpuidle/cpuidle-psci-domain.c | 267 ++++++++++++++++++++++++++
> > > > >  drivers/cpuidle/cpuidle-psci.c        |   4 +-
> > > > >  drivers/cpuidle/cpuidle-psci.h        |   5 +
> > > > >  3 files changed, 274 insertions(+), 2 deletions(-)
> > > > >
> > > > > diff --git a/drivers/cpuidle/cpuidle-psci-domain.c b/drivers/cpuidle/cpuidle-psci-domain.c
> > > > > index 656ef3d59149..c2f94ba42222 100644
> > > > > --- a/drivers/cpuidle/cpuidle-psci-domain.c
> > > > > +++ b/drivers/cpuidle/cpuidle-psci-domain.c
> > > > > @@ -7,14 +7,281 @@
> > > > >   *
> > > > >   */
> > > > >
> > > > > +#define pr_fmt(fmt) "CPUidle PSCI: " fmt
> > > > > +
> > > > >  #include <linux/cpu.h>
> > > > >  #include <linux/device.h>
> > > > >  #include <linux/kernel.h>
> > > > >  #include <linux/pm_domain.h>
> > > > >  #include <linux/pm_runtime.h>
> > > > > +#include <linux/psci.h>
> > > > > +#include <linux/slab.h>
> > > > > +#include <linux/string.h>
> > > > >
> > > > >  #include "cpuidle-psci.h"
> > > > >
> > > > > +struct psci_pd_provider {
> > > > > +     struct list_head link;
> > > > > +     struct device_node *node;
> > > > > +};
> > > > > +
> > > > > +static LIST_HEAD(psci_pd_providers);
> > > > > +static bool osi_mode_enabled;
> > > > > +
> > > > > +static int psci_pd_power_off(struct generic_pm_domain *pd)
> > > > > +{
> > > > > +     struct genpd_power_state *state = &pd->states[pd->state_idx];
> > > > > +     u32 *pd_state;
> > > > > +
> > > > > +     /* If we have failed to enable OSI mode, then abort power off. */
> > > > > +     if (!osi_mode_enabled)
> > > > > +             return -EBUSY;
> > > > > +
> > > >
> > > > Why is above check needed ? Shouldn't we have disable/remove pd of
> > > > OSI is not enabled ?
> > >
> > > Well, failing to enable OSI should in practice not happen, while it
> > > theoretically it could.
> > >
> >
> > I won't assume that. Since it's new and not tested yet, I prefer to assume
> > it can fail.
>
> Yes, I agree. Hence the degraded mode.
>
> >
> > > My approach to this has been to fall back to use a "degraded mode",
> > > which seems quite common for these kind of situations. The degraded
> > > mode means, we are preventing domain states from being used.
> > >
> >
> > But why can't we just fail registering or remove if already added.
>
> We can, but there are more problems with that than leaving this in a
> degraded mode, I think. See more below.
>
> > They are useless for "degraded mode" anyways. And it will ensure that
> > data->dev is NULL. Sorry now I see why you said it can be NULL but I
> > would rather not leave those unused genpd in place in case of error.
>
> data->dev would not be NULL in this case, because the
> dev_pm_domain_attach_by_name() which is called when we attach the CPU
> is going to return an error code, not NULL.
>
> That's because the connection is there in the DTB and thus it must
> fail, in this case it would be with -EPROBE_DEFER (waiting for a genpd
> provider to be registered).
>
> That would then lead to that the entire cpuidle-psci driver would fail
> to initiate/probe. In my opinion, I think it's better to fall back
> into a degraded mode, using all the idle states for the CPUs, but just
> preventing the cluster idle states.
>
> Just wanted to make this more clear for you to consider. I am happy to
> change in any way you suggest, but please confirm that you really want
> another behaviour than the degraded mode.
>

Sorry but if OSI set failed in firmware, it will be operating in default/
PC mode and I *don't* want to create genpd for that. It's confusing.
Even if you don't create all these genpd domains, it is still degraded
mode and we are anyway not changing that. Let me know if my understanding
is wrong here.

I am sure, DTB may get copied to different platform and the firmware may
not support OSI. I know we have logs, but creating and leaving those
genpd domains unused will be just confusing. Please change that.

--
Regards,
Sudeep

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 13/14] cpuidle: psci: Add support for PM domains by using genpd
  2019-12-20 10:07             ` Sudeep Holla
@ 2019-12-20 11:27               ` Ulf Hansson
  -1 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-20 11:27 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: Lorenzo Pieralisi, Rob Herring, Linux PM, Rafael J . Wysocki,
	Daniel Lezcano, Mark Rutland, Lina Iyer, Vincent Guittot,
	Stephen Boyd, Andy Gross, Bjorn Andersson, Kevin Hilman,
	Linux ARM, linux-arm-msm

On Fri, 20 Dec 2019 at 11:07, Sudeep Holla <sudeep.holla@arm.com> wrote:
>
> On Thu, Dec 19, 2019 at 11:02:40PM +0100, Ulf Hansson wrote:
> > On Thu, 19 Dec 2019 at 19:06, Sudeep Holla <sudeep.holla@arm.com> wrote:
> > >
> > > On Thu, Dec 19, 2019 at 04:48:39PM +0100, Ulf Hansson wrote:
> > > > On Thu, 19 Dec 2019 at 15:34, Sudeep Holla <sudeep.holla@arm.com> wrote:
> > > > >
> > > > > On Wed, Dec 11, 2019 at 04:43:42PM +0100, Ulf Hansson wrote:
> > > > > > When the hierarchical CPU topology layout is used in DT and the PSCI OSI
> > > > > > mode is supported by the PSCI FW, let's initialize a corresponding PM
> > > > > > domain topology by using genpd. This enables a CPU and a group of CPUs,
> > > > > > when attached to the topology, to be power-managed accordingly.
> > > > > >
> > > > > > To trigger the attempt to initialize the genpd data structures let's use a
> > > > > > subsys_initcall, which should be early enough to allow CPUs, but also other
> > > > > > devices to be attached.
> > > > > >
> > > > > > The initialization consists of parsing the PSCI OF node for the topology
> > > > > > and the "domain idle states" DT bindings. In case the idle states are
> > > > > > compatible with "domain-idle-state", the initialized genpd becomes
> > > > > > responsible of selecting an idle state for the PM domain, via assigning it
> > > > > > a genpd governor.
> > > > > >
> > > > > > Note that, a successful initialization of the genpd data structures, is
> > > > > > followed by a call to psci_set_osi_mode(), as to try to enable the OSI mode
> > > > > > in the PSCI FW. In case this fails, we fall back into a degraded mode
> > > > > > rather than bailing out and returning an error code.
> > > > > >
> > > > > > Co-developed-by: Lina Iyer <lina.iyer@linaro.org>
> > > > > > Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
> > > > > > Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> > > > > > ---
> > > > > >
> > > > > > Changes in v4:
> > > > > >       - None.
> > > > > >
> > > > > > ---
> > > > > >  drivers/cpuidle/cpuidle-psci-domain.c | 267 ++++++++++++++++++++++++++
> > > > > >  drivers/cpuidle/cpuidle-psci.c        |   4 +-
> > > > > >  drivers/cpuidle/cpuidle-psci.h        |   5 +
> > > > > >  3 files changed, 274 insertions(+), 2 deletions(-)
> > > > > >
> > > > > > diff --git a/drivers/cpuidle/cpuidle-psci-domain.c b/drivers/cpuidle/cpuidle-psci-domain.c
> > > > > > index 656ef3d59149..c2f94ba42222 100644
> > > > > > --- a/drivers/cpuidle/cpuidle-psci-domain.c
> > > > > > +++ b/drivers/cpuidle/cpuidle-psci-domain.c
> > > > > > @@ -7,14 +7,281 @@
> > > > > >   *
> > > > > >   */
> > > > > >
> > > > > > +#define pr_fmt(fmt) "CPUidle PSCI: " fmt
> > > > > > +
> > > > > >  #include <linux/cpu.h>
> > > > > >  #include <linux/device.h>
> > > > > >  #include <linux/kernel.h>
> > > > > >  #include <linux/pm_domain.h>
> > > > > >  #include <linux/pm_runtime.h>
> > > > > > +#include <linux/psci.h>
> > > > > > +#include <linux/slab.h>
> > > > > > +#include <linux/string.h>
> > > > > >
> > > > > >  #include "cpuidle-psci.h"
> > > > > >
> > > > > > +struct psci_pd_provider {
> > > > > > +     struct list_head link;
> > > > > > +     struct device_node *node;
> > > > > > +};
> > > > > > +
> > > > > > +static LIST_HEAD(psci_pd_providers);
> > > > > > +static bool osi_mode_enabled;
> > > > > > +
> > > > > > +static int psci_pd_power_off(struct generic_pm_domain *pd)
> > > > > > +{
> > > > > > +     struct genpd_power_state *state = &pd->states[pd->state_idx];
> > > > > > +     u32 *pd_state;
> > > > > > +
> > > > > > +     /* If we have failed to enable OSI mode, then abort power off. */
> > > > > > +     if (!osi_mode_enabled)
> > > > > > +             return -EBUSY;
> > > > > > +
> > > > >
> > > > > Why is above check needed ? Shouldn't we have disable/remove pd of
> > > > > OSI is not enabled ?
> > > >
> > > > Well, failing to enable OSI should in practice not happen, while it
> > > > theoretically it could.
> > > >
> > >
> > > I won't assume that. Since it's new and not tested yet, I prefer to assume
> > > it can fail.
> >
> > Yes, I agree. Hence the degraded mode.
> >
> > >
> > > > My approach to this has been to fall back to use a "degraded mode",
> > > > which seems quite common for these kind of situations. The degraded
> > > > mode means, we are preventing domain states from being used.
> > > >
> > >
> > > But why can't we just fail registering or remove if already added.
> >
> > We can, but there are more problems with that than leaving this in a
> > degraded mode, I think. See more below.
> >
> > > They are useless for "degraded mode" anyways. And it will ensure that
> > > data->dev is NULL. Sorry now I see why you said it can be NULL but I
> > > would rather not leave those unused genpd in place in case of error.
> >
> > data->dev would not be NULL in this case, because the
> > dev_pm_domain_attach_by_name() which is called when we attach the CPU
> > is going to return an error code, not NULL.
> >
> > That's because the connection is there in the DTB and thus it must
> > fail, in this case it would be with -EPROBE_DEFER (waiting for a genpd
> > provider to be registered).
> >
> > That would then lead to that the entire cpuidle-psci driver would fail
> > to initiate/probe. In my opinion, I think it's better to fall back
> > into a degraded mode, using all the idle states for the CPUs, but just
> > preventing the cluster idle states.
> >
> > Just wanted to make this more clear for you to consider. I am happy to
> > change in any way you suggest, but please confirm that you really want
> > another behaviour than the degraded mode.
> >
>
> Sorry but if OSI set failed in firmware, it will be operating in default/
> PC mode and I *don't* want to create genpd for that. It's confusing.

Alright, so that will cause some additional changes - let's agree how
to make those.

> Even if you don't create all these genpd domains, it is still degraded
> mode and we are anyway not changing that. Let me know if my understanding
> is wrong here.

Your understanding is wrong.

If I remove the genpds because psci_set_osi_mode() fails, then in the
current suggested initialization path, that will lead to that the
entire cpuidle-psci driver will fail to initiate (which is because
psci_dt_attach_cpu() returns an error). In other words, only WFI state
will be used by cpuidle as there will be no cpuidle driver registered
at all.

That would not be an acceptable behaviour, as it would make the
situation worse than today.

What we want in this scenario is to keep using all the idle states for
the CPUs, but ignores those for the cluster. That we both agree on,
right?

>
> I am sure, DTB may get copied to different platform and the firmware may
> not support OSI. I know we have logs, but creating and leaving those
> genpd domains unused will be just confusing. Please change that.

We are not creating any genpds unless OSI mode is supported. We do not
even try to attach CPUs to the PM domains, unless OSI mode is
supported. So this should already work according to your expectations
and previous requests.

To address your concern about removing genpds when psci_set_osi_mode()
fails, we also need to address the problems we get when calling
psci_dt_attach_cpu(). There are two viable options as I see it.

1. Prevent calling psci_dt_attach_cpu() altogether when
psci_set_osi_mode() failed. This means another function needs to be
shared from cpuidle-psci-domain.c to let cpuidle-psci.c know about it.

2. We can let psci_dt_attach_cpu() return NULL, when
psci_set_osi_mode() failed - as this information is already known by
cpuidle-psci-domain.c.

I vote for option 2, but what do you think?

Kind regards
Uffe

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 13/14] cpuidle: psci: Add support for PM domains by using genpd
@ 2019-12-20 11:27               ` Ulf Hansson
  0 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-20 11:27 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: Mark Rutland, Lorenzo Pieralisi, Linux PM, Stephen Boyd,
	linux-arm-msm, Daniel Lezcano, Rafael J . Wysocki, Andy Gross,
	Lina Iyer, Bjorn Andersson, Kevin Hilman, Rob Herring, Linux ARM

On Fri, 20 Dec 2019 at 11:07, Sudeep Holla <sudeep.holla@arm.com> wrote:
>
> On Thu, Dec 19, 2019 at 11:02:40PM +0100, Ulf Hansson wrote:
> > On Thu, 19 Dec 2019 at 19:06, Sudeep Holla <sudeep.holla@arm.com> wrote:
> > >
> > > On Thu, Dec 19, 2019 at 04:48:39PM +0100, Ulf Hansson wrote:
> > > > On Thu, 19 Dec 2019 at 15:34, Sudeep Holla <sudeep.holla@arm.com> wrote:
> > > > >
> > > > > On Wed, Dec 11, 2019 at 04:43:42PM +0100, Ulf Hansson wrote:
> > > > > > When the hierarchical CPU topology layout is used in DT and the PSCI OSI
> > > > > > mode is supported by the PSCI FW, let's initialize a corresponding PM
> > > > > > domain topology by using genpd. This enables a CPU and a group of CPUs,
> > > > > > when attached to the topology, to be power-managed accordingly.
> > > > > >
> > > > > > To trigger the attempt to initialize the genpd data structures let's use a
> > > > > > subsys_initcall, which should be early enough to allow CPUs, but also other
> > > > > > devices to be attached.
> > > > > >
> > > > > > The initialization consists of parsing the PSCI OF node for the topology
> > > > > > and the "domain idle states" DT bindings. In case the idle states are
> > > > > > compatible with "domain-idle-state", the initialized genpd becomes
> > > > > > responsible of selecting an idle state for the PM domain, via assigning it
> > > > > > a genpd governor.
> > > > > >
> > > > > > Note that, a successful initialization of the genpd data structures, is
> > > > > > followed by a call to psci_set_osi_mode(), as to try to enable the OSI mode
> > > > > > in the PSCI FW. In case this fails, we fall back into a degraded mode
> > > > > > rather than bailing out and returning an error code.
> > > > > >
> > > > > > Co-developed-by: Lina Iyer <lina.iyer@linaro.org>
> > > > > > Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
> > > > > > Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> > > > > > ---
> > > > > >
> > > > > > Changes in v4:
> > > > > >       - None.
> > > > > >
> > > > > > ---
> > > > > >  drivers/cpuidle/cpuidle-psci-domain.c | 267 ++++++++++++++++++++++++++
> > > > > >  drivers/cpuidle/cpuidle-psci.c        |   4 +-
> > > > > >  drivers/cpuidle/cpuidle-psci.h        |   5 +
> > > > > >  3 files changed, 274 insertions(+), 2 deletions(-)
> > > > > >
> > > > > > diff --git a/drivers/cpuidle/cpuidle-psci-domain.c b/drivers/cpuidle/cpuidle-psci-domain.c
> > > > > > index 656ef3d59149..c2f94ba42222 100644
> > > > > > --- a/drivers/cpuidle/cpuidle-psci-domain.c
> > > > > > +++ b/drivers/cpuidle/cpuidle-psci-domain.c
> > > > > > @@ -7,14 +7,281 @@
> > > > > >   *
> > > > > >   */
> > > > > >
> > > > > > +#define pr_fmt(fmt) "CPUidle PSCI: " fmt
> > > > > > +
> > > > > >  #include <linux/cpu.h>
> > > > > >  #include <linux/device.h>
> > > > > >  #include <linux/kernel.h>
> > > > > >  #include <linux/pm_domain.h>
> > > > > >  #include <linux/pm_runtime.h>
> > > > > > +#include <linux/psci.h>
> > > > > > +#include <linux/slab.h>
> > > > > > +#include <linux/string.h>
> > > > > >
> > > > > >  #include "cpuidle-psci.h"
> > > > > >
> > > > > > +struct psci_pd_provider {
> > > > > > +     struct list_head link;
> > > > > > +     struct device_node *node;
> > > > > > +};
> > > > > > +
> > > > > > +static LIST_HEAD(psci_pd_providers);
> > > > > > +static bool osi_mode_enabled;
> > > > > > +
> > > > > > +static int psci_pd_power_off(struct generic_pm_domain *pd)
> > > > > > +{
> > > > > > +     struct genpd_power_state *state = &pd->states[pd->state_idx];
> > > > > > +     u32 *pd_state;
> > > > > > +
> > > > > > +     /* If we have failed to enable OSI mode, then abort power off. */
> > > > > > +     if (!osi_mode_enabled)
> > > > > > +             return -EBUSY;
> > > > > > +
> > > > >
> > > > > Why is above check needed ? Shouldn't we have disable/remove pd of
> > > > > OSI is not enabled ?
> > > >
> > > > Well, failing to enable OSI should in practice not happen, while it
> > > > theoretically it could.
> > > >
> > >
> > > I won't assume that. Since it's new and not tested yet, I prefer to assume
> > > it can fail.
> >
> > Yes, I agree. Hence the degraded mode.
> >
> > >
> > > > My approach to this has been to fall back to use a "degraded mode",
> > > > which seems quite common for these kind of situations. The degraded
> > > > mode means, we are preventing domain states from being used.
> > > >
> > >
> > > But why can't we just fail registering or remove if already added.
> >
> > We can, but there are more problems with that than leaving this in a
> > degraded mode, I think. See more below.
> >
> > > They are useless for "degraded mode" anyways. And it will ensure that
> > > data->dev is NULL. Sorry now I see why you said it can be NULL but I
> > > would rather not leave those unused genpd in place in case of error.
> >
> > data->dev would not be NULL in this case, because the
> > dev_pm_domain_attach_by_name() which is called when we attach the CPU
> > is going to return an error code, not NULL.
> >
> > That's because the connection is there in the DTB and thus it must
> > fail, in this case it would be with -EPROBE_DEFER (waiting for a genpd
> > provider to be registered).
> >
> > That would then lead to that the entire cpuidle-psci driver would fail
> > to initiate/probe. In my opinion, I think it's better to fall back
> > into a degraded mode, using all the idle states for the CPUs, but just
> > preventing the cluster idle states.
> >
> > Just wanted to make this more clear for you to consider. I am happy to
> > change in any way you suggest, but please confirm that you really want
> > another behaviour than the degraded mode.
> >
>
> Sorry but if OSI set failed in firmware, it will be operating in default/
> PC mode and I *don't* want to create genpd for that. It's confusing.

Alright, so that will cause some additional changes - let's agree how
to make those.

> Even if you don't create all these genpd domains, it is still degraded
> mode and we are anyway not changing that. Let me know if my understanding
> is wrong here.

Your understanding is wrong.

If I remove the genpds because psci_set_osi_mode() fails, then in the
current suggested initialization path, that will lead to that the
entire cpuidle-psci driver will fail to initiate (which is because
psci_dt_attach_cpu() returns an error). In other words, only WFI state
will be used by cpuidle as there will be no cpuidle driver registered
at all.

That would not be an acceptable behaviour, as it would make the
situation worse than today.

What we want in this scenario is to keep using all the idle states for
the CPUs, but ignores those for the cluster. That we both agree on,
right?

>
> I am sure, DTB may get copied to different platform and the firmware may
> not support OSI. I know we have logs, but creating and leaving those
> genpd domains unused will be just confusing. Please change that.

We are not creating any genpds unless OSI mode is supported. We do not
even try to attach CPUs to the PM domains, unless OSI mode is
supported. So this should already work according to your expectations
and previous requests.

To address your concern about removing genpds when psci_set_osi_mode()
fails, we also need to address the problems we get when calling
psci_dt_attach_cpu(). There are two viable options as I see it.

1. Prevent calling psci_dt_attach_cpu() altogether when
psci_set_osi_mode() failed. This means another function needs to be
shared from cpuidle-psci-domain.c to let cpuidle-psci.c know about it.

2. We can let psci_dt_attach_cpu() return NULL, when
psci_set_osi_mode() failed - as this information is already known by
cpuidle-psci-domain.c.

I vote for option 2, but what do you think?

Kind regards
Uffe

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 10/14] cpuidle: psci: Prepare to use OS initiated suspend mode via PM domains
  2019-12-20 10:01             ` Sudeep Holla
@ 2019-12-20 11:33               ` Ulf Hansson
  -1 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-20 11:33 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: Lorenzo Pieralisi, Rob Herring, Linux PM, Rafael J . Wysocki,
	Daniel Lezcano, Mark Rutland, Lina Iyer, Vincent Guittot,
	Stephen Boyd, Andy Gross, Bjorn Andersson, Kevin Hilman,
	Linux ARM, linux-arm-msm

On Fri, 20 Dec 2019 at 11:01, Sudeep Holla <sudeep.holla@arm.com> wrote:
>
> On Thu, Dec 19, 2019 at 10:33:34PM +0100, Ulf Hansson wrote:
> > On Thu, 19 Dec 2019 at 19:01, Sudeep Holla <sudeep.holla@arm.com> wrote:
> > >
> > > On Thu, Dec 19, 2019 at 04:48:13PM +0100, Ulf Hansson wrote:
> > > > On Thu, 19 Dec 2019 at 15:32, Sudeep Holla <sudeep.holla@arm.com> wrote:
> > > > >
> > > > > On Wed, Dec 11, 2019 at 04:43:39PM +0100, Ulf Hansson wrote:
> > > > > > The per CPU variable psci_power_state, contains an array of fixed values,
> > > > > > which reflects the corresponding arm,psci-suspend-param parsed from DT, for
> > > > > > each of the available CPU idle states.
> > > > > >
> > > > > > This isn't sufficient when using the hierarchical CPU topology in DT, in
> > > > > > combination with having PSCI OS initiated (OSI) mode enabled. More
> > > > > > precisely, in OSI mode, Linux is responsible of telling the PSCI FW what
> > > > > > idle state the cluster (a group of CPUs) should enter, while in PSCI
> > > > > > Platform Coordinated (PC) mode, each CPU independently votes for an idle
> > > > > > state of the cluster.
> > > > > >
> > > > > > For this reason, introduce a per CPU variable called domain_state and
> > > > > > implement two helper functions to read/write its value. Then let the
> > > > > > domain_state take precedence over the regular selected state, when entering
> > > > > > and idle state.
> > > > > >
> > > > > > To avoid executing the above OSI specific code in the ->enter() callback,
> > > > > > while operating in the default PSCI Platform Coordinated mode, let's also
> > > > > > add a new enter-function and use it for OSI.
> > > > > >
> > > > > > Co-developed-by: Lina Iyer <lina.iyer@linaro.org>
> > > > > > Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
> > > > > > Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> > > > > > ---
> > > > > >
> > > > > > Changes in v4:
> > > > > >       - Rebased on top of earlier changes.
> > > > > >       - Add comment about using the deepest cpuidle state for the domain state
> > > > > >       selection.
> > > > > >
> > > > > > ---
> > > > > >  drivers/cpuidle/cpuidle-psci.c | 56 ++++++++++++++++++++++++++++++----
> > > > > >  1 file changed, 50 insertions(+), 6 deletions(-)
> > > > > >
> > > > > > diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c
> > > > > > index 6a87848be3c3..9600fe674a89 100644
> > > > > > --- a/drivers/cpuidle/cpuidle-psci.c
> > > > > > +++ b/drivers/cpuidle/cpuidle-psci.c
> > > > > > @@ -29,14 +29,47 @@ struct psci_cpuidle_data {
> > > > > >  };
> > > > > >
> > > > > >  static DEFINE_PER_CPU_READ_MOSTLY(struct psci_cpuidle_data, psci_cpuidle_data);
> > > > > > +static DEFINE_PER_CPU(u32, domain_state);
> > > > > > +
> > > > >
> > > > > [...]
> > > > >
> > > > > > +static int psci_enter_domain_idle_state(struct cpuidle_device *dev,
> > > > > > +                                     struct cpuidle_driver *drv, int idx)
> > > > > > +{
> > > > > > +     struct psci_cpuidle_data *data = this_cpu_ptr(&psci_cpuidle_data);
> > > > > > +     u32 *states = data->psci_states;
> > > > >
> > > > > Why can't the above be like this for consistency(see below in
> > > > > psci_enter_idle_state) ?
> > > >
> > > > You have a point, however in patch11 I am adding this line below.
> > > >
> > > > struct device *pd_dev = data->dev;
> > > >
> > > > So I don't think it matters much, agree?
> > > >
> > >
> > > Ah OK, looked odd as part of this patch, may be you could have moved
> > > this change into that patch. Anyways fine as is.
> >
> > Okay, then I rather just keep it.
> >
> > >
> > > > >
> > > > >         u32 *states = __this_cpu_read(psci_cpuidle_data.psci_states);
> > > > >
> > > > > > +     u32 state = psci_get_domain_state();
> > > > > > +     int ret;
> > > > > > +
> > > > > > +     if (!state)
> > > > > > +             state = states[idx];
> > > > > > +
> > > > > > +     ret = psci_enter_state(idx, state);
> > > > > > +
> > > > > > +     /* Clear the domain state to start fresh when back from idle. */
> > > > > > +     psci_set_domain_state(0);
> > > > > > +     return ret;
> > > > > > +}
> > > > > >
> > > > >
> > > > > [...]
> > > > >
> > > > > > @@ -118,6 +152,15 @@ static int __init psci_dt_cpu_init_idle(struct device_node *cpu_node,
> > > > > >                       ret = PTR_ERR(data->dev);
> > > > > >                       goto free_mem;
> > > > > >               }
> > > > > > +
> > > > > > +             /*
> > > > > > +              * Using the deepest state for the CPU to trigger a potential
> > > > > > +              * selection of a shared state for the domain, assumes the
> > > > > > +              * domain states are all deeper states.
> > > > > > +              */
> > > > > > +             if (data->dev)
> > > > >
> > > > > You can drop this check as return on error above.
> > > >
> > > > Actually not, because if OSI is supported, there is still a
> > > > possibility that the PM domain topology isn't used.
> > > >
> > >
> > > And how do we support that ? I am missing something here.
> > >
> > > > This means ->data->dev is NULL.
> > > >
> > >
> > > I don't get that.
> >
> > This is quite similar to the existing limited support we have for OSI today.
> >
> > We are using the idle states for the CPU, but ignoring the idle states
> > for the cluster. If you just skip applying the DTS patch14, this is
> > what happens.
> >
>
> No if psci_set_osi fails, we shouldn't create genpd domain as we don't
> enter any cluster state. The default mode(same as PC) should work which
> don't need any genpd domains. Adding one which is unused is just confusion.
> Please avoid that.

I am deferring to the other thread to continue this discussion.

>
> > >
> > > > >
> > > > > > +                     drv->states[state_count - 1].enter =
> > > > > > +                             psci_enter_domain_idle_state;
> > > > >
> > > > > I see the comment above but this potential blocks retention mode at
> > > > > cluster level when all cpu enter retention at CPU level. I don't like
> > > > > this assumption, but I don't have any better suggestion. Please add the
> > > > > note that we can't enter RETENTION state at cluster/domain level when
> > > > > all CPUs enter at CPU level.
> > > >
> > > > You are correct, but I think the comment a few lines above (agreed to
> > > > be added by Lorenzo in the previous version) should be enough to
> > > > explain that. No?
> > > >
> > > > The point is, this is only a problem if cluster RETENTION is
> > > > considered to be a shallower state that CPU power off, for example.
> > > >
> > >
> > > Yes, but give examples makes it better and helps people who may be
> > > wondering why cluster retention state is not being entered. You can just
> > > add to the above comment:
> > >
> > > "e.g. If CPU Retention is one of the shallower state, then we can't enter
> > > any of the allowed domain states."
> >
> > Hmm, that it's not a correct statement I think, let me elaborate.
> >
> > The problem is, that in case the CPU has both RETENTION and POWER OFF
> > (deepest CPU state), we would only be able to reach a cluster state
> > (RETENTION or POWER OFF) when the CPUs are in CPU POWER OFF (as that's
> > the deepest).
> >
>
> Sorry for the poor choice of words. What I meant is only one can be
> deepest and it will be CPU POWER OFF if it exist at the CPU level.
> RETENTION(again if exist) is shallower(rather deeper but not deepest
> state).
>
> > This is okay, as long as a cluster RETENTION state is considered being
> > "deeper" than the CPU POWER OFF state. However, if that isn't the
> > case, it means  the cluster RETENTION state is not considered in the
> > correct order, but it's still possible to reach as a "domain state".
> >
>
> Again sorry for not being clear, I was referring CPU RET + CLUSTER RET.
>
> > I think this all is kind of summarized in the comment I agreed upon
> > with Lorenzo, but if you still think there is some clarification
> > needed I happy to add it.
> >
> > Makes sense?
> >
>
> OK, if you happy, that's fine. I just wanted to clearly state CPU RET
> + CLUSTER RET is not possible with the implementation.

Okay!

I will then leave this as is. When/if you find a better wording of the
comment, you can always send a patch on top.

Kind regards
Uffe

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 10/14] cpuidle: psci: Prepare to use OS initiated suspend mode via PM domains
@ 2019-12-20 11:33               ` Ulf Hansson
  0 siblings, 0 replies; 76+ messages in thread
From: Ulf Hansson @ 2019-12-20 11:33 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: Mark Rutland, Lorenzo Pieralisi, Linux PM, Stephen Boyd,
	linux-arm-msm, Daniel Lezcano, Rafael J . Wysocki, Andy Gross,
	Lina Iyer, Bjorn Andersson, Kevin Hilman, Rob Herring, Linux ARM

On Fri, 20 Dec 2019 at 11:01, Sudeep Holla <sudeep.holla@arm.com> wrote:
>
> On Thu, Dec 19, 2019 at 10:33:34PM +0100, Ulf Hansson wrote:
> > On Thu, 19 Dec 2019 at 19:01, Sudeep Holla <sudeep.holla@arm.com> wrote:
> > >
> > > On Thu, Dec 19, 2019 at 04:48:13PM +0100, Ulf Hansson wrote:
> > > > On Thu, 19 Dec 2019 at 15:32, Sudeep Holla <sudeep.holla@arm.com> wrote:
> > > > >
> > > > > On Wed, Dec 11, 2019 at 04:43:39PM +0100, Ulf Hansson wrote:
> > > > > > The per CPU variable psci_power_state, contains an array of fixed values,
> > > > > > which reflects the corresponding arm,psci-suspend-param parsed from DT, for
> > > > > > each of the available CPU idle states.
> > > > > >
> > > > > > This isn't sufficient when using the hierarchical CPU topology in DT, in
> > > > > > combination with having PSCI OS initiated (OSI) mode enabled. More
> > > > > > precisely, in OSI mode, Linux is responsible of telling the PSCI FW what
> > > > > > idle state the cluster (a group of CPUs) should enter, while in PSCI
> > > > > > Platform Coordinated (PC) mode, each CPU independently votes for an idle
> > > > > > state of the cluster.
> > > > > >
> > > > > > For this reason, introduce a per CPU variable called domain_state and
> > > > > > implement two helper functions to read/write its value. Then let the
> > > > > > domain_state take precedence over the regular selected state, when entering
> > > > > > and idle state.
> > > > > >
> > > > > > To avoid executing the above OSI specific code in the ->enter() callback,
> > > > > > while operating in the default PSCI Platform Coordinated mode, let's also
> > > > > > add a new enter-function and use it for OSI.
> > > > > >
> > > > > > Co-developed-by: Lina Iyer <lina.iyer@linaro.org>
> > > > > > Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
> > > > > > Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> > > > > > ---
> > > > > >
> > > > > > Changes in v4:
> > > > > >       - Rebased on top of earlier changes.
> > > > > >       - Add comment about using the deepest cpuidle state for the domain state
> > > > > >       selection.
> > > > > >
> > > > > > ---
> > > > > >  drivers/cpuidle/cpuidle-psci.c | 56 ++++++++++++++++++++++++++++++----
> > > > > >  1 file changed, 50 insertions(+), 6 deletions(-)
> > > > > >
> > > > > > diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c
> > > > > > index 6a87848be3c3..9600fe674a89 100644
> > > > > > --- a/drivers/cpuidle/cpuidle-psci.c
> > > > > > +++ b/drivers/cpuidle/cpuidle-psci.c
> > > > > > @@ -29,14 +29,47 @@ struct psci_cpuidle_data {
> > > > > >  };
> > > > > >
> > > > > >  static DEFINE_PER_CPU_READ_MOSTLY(struct psci_cpuidle_data, psci_cpuidle_data);
> > > > > > +static DEFINE_PER_CPU(u32, domain_state);
> > > > > > +
> > > > >
> > > > > [...]
> > > > >
> > > > > > +static int psci_enter_domain_idle_state(struct cpuidle_device *dev,
> > > > > > +                                     struct cpuidle_driver *drv, int idx)
> > > > > > +{
> > > > > > +     struct psci_cpuidle_data *data = this_cpu_ptr(&psci_cpuidle_data);
> > > > > > +     u32 *states = data->psci_states;
> > > > >
> > > > > Why can't the above be like this for consistency(see below in
> > > > > psci_enter_idle_state) ?
> > > >
> > > > You have a point, however in patch11 I am adding this line below.
> > > >
> > > > struct device *pd_dev = data->dev;
> > > >
> > > > So I don't think it matters much, agree?
> > > >
> > >
> > > Ah OK, looked odd as part of this patch, may be you could have moved
> > > this change into that patch. Anyways fine as is.
> >
> > Okay, then I rather just keep it.
> >
> > >
> > > > >
> > > > >         u32 *states = __this_cpu_read(psci_cpuidle_data.psci_states);
> > > > >
> > > > > > +     u32 state = psci_get_domain_state();
> > > > > > +     int ret;
> > > > > > +
> > > > > > +     if (!state)
> > > > > > +             state = states[idx];
> > > > > > +
> > > > > > +     ret = psci_enter_state(idx, state);
> > > > > > +
> > > > > > +     /* Clear the domain state to start fresh when back from idle. */
> > > > > > +     psci_set_domain_state(0);
> > > > > > +     return ret;
> > > > > > +}
> > > > > >
> > > > >
> > > > > [...]
> > > > >
> > > > > > @@ -118,6 +152,15 @@ static int __init psci_dt_cpu_init_idle(struct device_node *cpu_node,
> > > > > >                       ret = PTR_ERR(data->dev);
> > > > > >                       goto free_mem;
> > > > > >               }
> > > > > > +
> > > > > > +             /*
> > > > > > +              * Using the deepest state for the CPU to trigger a potential
> > > > > > +              * selection of a shared state for the domain, assumes the
> > > > > > +              * domain states are all deeper states.
> > > > > > +              */
> > > > > > +             if (data->dev)
> > > > >
> > > > > You can drop this check as return on error above.
> > > >
> > > > Actually not, because if OSI is supported, there is still a
> > > > possibility that the PM domain topology isn't used.
> > > >
> > >
> > > And how do we support that ? I am missing something here.
> > >
> > > > This means ->data->dev is NULL.
> > > >
> > >
> > > I don't get that.
> >
> > This is quite similar to the existing limited support we have for OSI today.
> >
> > We are using the idle states for the CPU, but ignoring the idle states
> > for the cluster. If you just skip applying the DTS patch14, this is
> > what happens.
> >
>
> No if psci_set_osi fails, we shouldn't create genpd domain as we don't
> enter any cluster state. The default mode(same as PC) should work which
> don't need any genpd domains. Adding one which is unused is just confusion.
> Please avoid that.

I am deferring to the other thread to continue this discussion.

>
> > >
> > > > >
> > > > > > +                     drv->states[state_count - 1].enter =
> > > > > > +                             psci_enter_domain_idle_state;
> > > > >
> > > > > I see the comment above but this potential blocks retention mode at
> > > > > cluster level when all cpu enter retention at CPU level. I don't like
> > > > > this assumption, but I don't have any better suggestion. Please add the
> > > > > note that we can't enter RETENTION state at cluster/domain level when
> > > > > all CPUs enter at CPU level.
> > > >
> > > > You are correct, but I think the comment a few lines above (agreed to
> > > > be added by Lorenzo in the previous version) should be enough to
> > > > explain that. No?
> > > >
> > > > The point is, this is only a problem if cluster RETENTION is
> > > > considered to be a shallower state that CPU power off, for example.
> > > >
> > >
> > > Yes, but give examples makes it better and helps people who may be
> > > wondering why cluster retention state is not being entered. You can just
> > > add to the above comment:
> > >
> > > "e.g. If CPU Retention is one of the shallower state, then we can't enter
> > > any of the allowed domain states."
> >
> > Hmm, that it's not a correct statement I think, let me elaborate.
> >
> > The problem is, that in case the CPU has both RETENTION and POWER OFF
> > (deepest CPU state), we would only be able to reach a cluster state
> > (RETENTION or POWER OFF) when the CPUs are in CPU POWER OFF (as that's
> > the deepest).
> >
>
> Sorry for the poor choice of words. What I meant is only one can be
> deepest and it will be CPU POWER OFF if it exist at the CPU level.
> RETENTION(again if exist) is shallower(rather deeper but not deepest
> state).
>
> > This is okay, as long as a cluster RETENTION state is considered being
> > "deeper" than the CPU POWER OFF state. However, if that isn't the
> > case, it means  the cluster RETENTION state is not considered in the
> > correct order, but it's still possible to reach as a "domain state".
> >
>
> Again sorry for not being clear, I was referring CPU RET + CLUSTER RET.
>
> > I think this all is kind of summarized in the comment I agreed upon
> > with Lorenzo, but if you still think there is some clarification
> > needed I happy to add it.
> >
> > Makes sense?
> >
>
> OK, if you happy, that's fine. I just wanted to clearly state CPU RET
> + CLUSTER RET is not possible with the implementation.

Okay!

I will then leave this as is. When/if you find a better wording of the
comment, you can always send a patch on top.

Kind regards
Uffe

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 13/14] cpuidle: psci: Add support for PM domains by using genpd
  2019-12-20 11:27               ` Ulf Hansson
@ 2019-12-20 12:01                 ` Sudeep Holla
  -1 siblings, 0 replies; 76+ messages in thread
From: Sudeep Holla @ 2019-12-20 12:01 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Lorenzo Pieralisi, Rob Herring, Linux PM, Rafael J . Wysocki,
	Daniel Lezcano, Mark Rutland, Lina Iyer, Vincent Guittot,
	Stephen Boyd, Andy Gross, Bjorn Andersson, Kevin Hilman,
	Sudeep Holla, Linux ARM, linux-arm-msm

On Fri, Dec 20, 2019 at 12:27:39PM +0100, Ulf Hansson wrote:
> On Fri, 20 Dec 2019 at 11:07, Sudeep Holla <sudeep.holla@arm.com> wrote:

[...]

> >
> > Even if you don't create all these genpd domains, it is still degraded
> > mode and we are anyway not changing that. Let me know if my understanding
> > is wrong here.
>
> Your understanding is wrong.
>
> If I remove the genpds because psci_set_osi_mode() fails, then in the
> current suggested initialization path, that will lead to that the
> entire cpuidle-psci driver will fail to initiate (which is because
> psci_dt_attach_cpu() returns an error). In other words, only WFI state
> will be used by cpuidle as there will be no cpuidle driver registered
> at all.
>
> That would not be an acceptable behaviour, as it would make the
> situation worse than today.
>
> What we want in this scenario is to keep using all the idle states for
> the CPUs, but ignores those for the cluster. That we both agree on,
> right?
>

Yes, I agree and understand that. I was assuming as part of this change
you will fixup psci_dt_cpu_init_idle not to return error but just allow
CPU level idle. Sorry if that was not clear, I was always assuming that.

> >
> > I am sure, DTB may get copied to different platform and the firmware may
> > not support OSI. I know we have logs, but creating and leaving those
> > genpd domains unused will be just confusing. Please change that.
>
> We are not creating any genpds unless OSI mode is supported. We do not
> even try to attach CPUs to the PM domains, unless OSI mode is
> supported. So this should already work according to your expectations
> and previous requests.
>

Yes I understand, but checking if "OSI mode is supported" is not same as
"setting OSI mode". Until OSI mode is set, it is default/PC mode, so we
need to work based on that assumption.

> To address your concern about removing genpds when psci_set_osi_mode()
> fails, we also need to address the problems we get when calling
> psci_dt_attach_cpu(). There are two viable options as I see it.
>

Shouldn't that fail ? Sorry, I might be missing something.

> 1. Prevent calling psci_dt_attach_cpu() altogether when
> psci_set_osi_mode() failed. This means another function needs to be
> shared from cpuidle-psci-domain.c to let cpuidle-psci.c know about it.
>

If we don't create any genpd, will psci_dt_attach_cpu fail ?

> 2. We can let psci_dt_attach_cpu() return NULL, when
> psci_set_osi_mode() failed - as this information is already known by
> cpuidle-psci-domain.c.
>

Yes I was making all the arguments/discussion based on that. Do you see
any issues with that ? Any races possible ?

> I vote for option 2, but what do you think?
>

Me too from the time I started the discussion, I assume a lot and
don't put this into words in the email.

--
Regards,
Sudeep

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v4 13/14] cpuidle: psci: Add support for PM domains by using genpd
@ 2019-12-20 12:01                 ` Sudeep Holla
  0 siblings, 0 replies; 76+ messages in thread
From: Sudeep Holla @ 2019-12-20 12:01 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Mark Rutland, Lorenzo Pieralisi, Linux PM, Stephen Boyd,
	linux-arm-msm, Daniel Lezcano, Rafael J . Wysocki, Andy Gross,
	Lina Iyer, Bjorn Andersson, Kevin Hilman, Rob Herring,
	Sudeep Holla, Linux ARM

On Fri, Dec 20, 2019 at 12:27:39PM +0100, Ulf Hansson wrote:
> On Fri, 20 Dec 2019 at 11:07, Sudeep Holla <sudeep.holla@arm.com> wrote:

[...]

> >
> > Even if you don't create all these genpd domains, it is still degraded
> > mode and we are anyway not changing that. Let me know if my understanding
> > is wrong here.
>
> Your understanding is wrong.
>
> If I remove the genpds because psci_set_osi_mode() fails, then in the
> current suggested initialization path, that will lead to that the
> entire cpuidle-psci driver will fail to initiate (which is because
> psci_dt_attach_cpu() returns an error). In other words, only WFI state
> will be used by cpuidle as there will be no cpuidle driver registered
> at all.
>
> That would not be an acceptable behaviour, as it would make the
> situation worse than today.
>
> What we want in this scenario is to keep using all the idle states for
> the CPUs, but ignores those for the cluster. That we both agree on,
> right?
>

Yes, I agree and understand that. I was assuming as part of this change
you will fixup psci_dt_cpu_init_idle not to return error but just allow
CPU level idle. Sorry if that was not clear, I was always assuming that.

> >
> > I am sure, DTB may get copied to different platform and the firmware may
> > not support OSI. I know we have logs, but creating and leaving those
> > genpd domains unused will be just confusing. Please change that.
>
> We are not creating any genpds unless OSI mode is supported. We do not
> even try to attach CPUs to the PM domains, unless OSI mode is
> supported. So this should already work according to your expectations
> and previous requests.
>

Yes I understand, but checking if "OSI mode is supported" is not same as
"setting OSI mode". Until OSI mode is set, it is default/PC mode, so we
need to work based on that assumption.

> To address your concern about removing genpds when psci_set_osi_mode()
> fails, we also need to address the problems we get when calling
> psci_dt_attach_cpu(). There are two viable options as I see it.
>

Shouldn't that fail ? Sorry, I might be missing something.

> 1. Prevent calling psci_dt_attach_cpu() altogether when
> psci_set_osi_mode() failed. This means another function needs to be
> shared from cpuidle-psci-domain.c to let cpuidle-psci.c know about it.
>

If we don't create any genpd, will psci_dt_attach_cpu fail ?

> 2. We can let psci_dt_attach_cpu() return NULL, when
> psci_set_osi_mode() failed - as this information is already known by
> cpuidle-psci-domain.c.
>

Yes I was making all the arguments/discussion based on that. Do you see
any issues with that ? Any races possible ?

> I vote for option 2, but what do you think?
>

Me too from the time I started the discussion, I assume a lot and
don't put this into words in the email.

--
Regards,
Sudeep

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 76+ messages in thread

end of thread, other threads:[~2019-12-20 12:01 UTC | newest]

Thread overview: 76+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-11 15:43 [PATCH v4 00/14] cpuidle: psci: Support hierarchical CPU arrangement Ulf Hansson
2019-12-11 15:43 ` Ulf Hansson
2019-12-11 15:43 ` [PATCH v4 01/14] cpuidle: psci: Align psci_power_state count with idle state count Ulf Hansson
2019-12-11 15:43   ` Ulf Hansson
2019-12-11 15:43 ` [PATCH v4 02/14] dt: psci: Update DT bindings to support hierarchical PSCI states Ulf Hansson
2019-12-11 15:43   ` Ulf Hansson
2019-12-11 15:43 ` [PATCH v4 03/14] firmware: psci: Export functions to manage the OSI mode Ulf Hansson
2019-12-11 15:43   ` Ulf Hansson
2019-12-11 15:43 ` [PATCH v4 04/14] of: base: Add of_get_cpu_state_node() to get idle states for a CPU node Ulf Hansson
2019-12-11 15:43   ` Ulf Hansson
2019-12-11 15:43 ` [PATCH v4 05/14] cpuidle: dt: Support hierarchical CPU idle states Ulf Hansson
2019-12-11 15:43   ` Ulf Hansson
2019-12-11 15:43 ` [PATCH v4 06/14] cpuidle: psci: Simplify OF parsing of CPU idle state nodes Ulf Hansson
2019-12-11 15:43   ` Ulf Hansson
2019-12-11 15:43 ` [PATCH v4 07/14] cpuidle: psci: Support hierarchical CPU idle states Ulf Hansson
2019-12-11 15:43   ` Ulf Hansson
2019-12-11 15:43 ` [PATCH v4 08/14] cpuidle: psci: Add a helper to attach a CPU to its PM domain Ulf Hansson
2019-12-11 15:43   ` Ulf Hansson
2019-12-19 14:30   ` Sudeep Holla
2019-12-19 14:30     ` Sudeep Holla
2019-12-11 15:43 ` [PATCH v4 09/14] cpuidle: psci: Attach CPU devices to their PM domains Ulf Hansson
2019-12-11 15:43   ` Ulf Hansson
2019-12-19 14:30   ` Sudeep Holla
2019-12-19 14:30     ` Sudeep Holla
2019-12-11 15:43 ` [PATCH v4 10/14] cpuidle: psci: Prepare to use OS initiated suspend mode via " Ulf Hansson
2019-12-11 15:43   ` Ulf Hansson
2019-12-19 14:31   ` Sudeep Holla
2019-12-19 14:31     ` Sudeep Holla
2019-12-19 15:48     ` Ulf Hansson
2019-12-19 15:48       ` Ulf Hansson
2019-12-19 18:01       ` Sudeep Holla
2019-12-19 18:01         ` Sudeep Holla
2019-12-19 21:33         ` Ulf Hansson
2019-12-19 21:33           ` Ulf Hansson
2019-12-20 10:01           ` Sudeep Holla
2019-12-20 10:01             ` Sudeep Holla
2019-12-20 11:33             ` Ulf Hansson
2019-12-20 11:33               ` Ulf Hansson
2019-12-11 15:43 ` [PATCH v4 11/14] cpuidle: psci: Manage runtime PM in the idle path Ulf Hansson
2019-12-11 15:43   ` Ulf Hansson
2019-12-19 14:32   ` Sudeep Holla
2019-12-19 14:32     ` Sudeep Holla
2019-12-11 15:43 ` [PATCH v4 12/14] cpuidle: psci: Support CPU hotplug for the hierarchical model Ulf Hansson
2019-12-11 15:43   ` Ulf Hansson
2019-12-19 14:33   ` Sudeep Holla
2019-12-19 14:33     ` Sudeep Holla
2019-12-19 15:48     ` Ulf Hansson
2019-12-19 15:48       ` Ulf Hansson
2019-12-11 15:43 ` [PATCH v4 13/14] cpuidle: psci: Add support for PM domains by using genpd Ulf Hansson
2019-12-11 15:43   ` Ulf Hansson
2019-12-19 14:34   ` Sudeep Holla
2019-12-19 14:34     ` Sudeep Holla
2019-12-19 15:48     ` Ulf Hansson
2019-12-19 15:48       ` Ulf Hansson
2019-12-19 18:06       ` Sudeep Holla
2019-12-19 18:06         ` Sudeep Holla
2019-12-19 22:02         ` Ulf Hansson
2019-12-19 22:02           ` Ulf Hansson
2019-12-20 10:07           ` Sudeep Holla
2019-12-20 10:07             ` Sudeep Holla
2019-12-20 11:27             ` Ulf Hansson
2019-12-20 11:27               ` Ulf Hansson
2019-12-20 12:01               ` Sudeep Holla
2019-12-20 12:01                 ` Sudeep Holla
2019-12-11 15:43 ` [PATCH v4 14/14] arm64: dts: Convert to the hierarchical CPU topology layout for MSM8916 Ulf Hansson
2019-12-11 15:43   ` Ulf Hansson
2019-12-19 14:34   ` Sudeep Holla
2019-12-19 14:34     ` Sudeep Holla
2019-12-19 15:48     ` Ulf Hansson
2019-12-19 15:48       ` Ulf Hansson
2019-12-19 17:58       ` Sudeep Holla
2019-12-19 17:58         ` Sudeep Holla
2019-12-18  7:36 ` [PATCH v4 00/14] cpuidle: psci: Support hierarchical CPU arrangement Ulf Hansson
2019-12-18  7:36   ` Ulf Hansson
2019-12-18 10:25   ` Sudeep Holla
2019-12-18 10:25     ` Sudeep Holla

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.