[v2] SLW: Provide cpuidle state description in device tree

Message ID 20180604080505.103996-1-huntbag@linux.vnet.ibm.com
State New
Headers show
Series
  • [v2] SLW: Provide cpuidle state description in device tree
Related show

Commit Message

Abhishek Goel June 4, 2018, 8:05 a.m.
This patch adds description for every cpuidle state and expose it
through device tree. Up until now, name was being used for description
as no description was provided for cpuidle states.
The description for idle states in case of POWER can be printed
using "cpupower monitor -l" or "cpupower idle-info".

Signed-off-by: Abhishek Goel <huntbag@linux.vnet.ibm.com>
---
 doc/device-tree/ibm,opal/power-mgt.rst |  5 ++++
 hw/slw.c                               | 49 +++++++++++++++++++++++++++++-----
 2 files changed, 48 insertions(+), 6 deletions(-)

Comments

ppaidipe June 4, 2018, 8:49 a.m. | #1
On 2018-06-04 13:35, Abhishek Goel wrote:
> This patch adds description for every cpuidle state and expose it
> through device tree. Up until now, name was being used for description
> as no description was provided for cpuidle states.
> The description for idle states in case of POWER can be printed
> using "cpupower monitor -l" or "cpupower idle-info".
> 
> Signed-off-by: Abhishek Goel <huntbag@linux.vnet.ibm.com>
> ---
>  doc/device-tree/ibm,opal/power-mgt.rst |  5 ++++
>  hw/slw.c                               | 49 
> +++++++++++++++++++++++++++++-----
>  2 files changed, 48 insertions(+), 6 deletions(-)
> 
> diff --git a/doc/device-tree/ibm,opal/power-mgt.rst
> b/doc/device-tree/ibm,opal/power-mgt.rst
> index b326a24b..598f8651 100644
> --- a/doc/device-tree/ibm,opal/power-mgt.rst
> +++ b/doc/device-tree/ibm,opal/power-mgt.rst
> @@ -10,6 +10,10 @@ ibm,opal/power-mgt device tree entries
> 
> 
>  All available CPU idle states are listed in ibm,cpu-idle-state-names
> +The description field for cpuidle states describes the impact of that
> +idle state. It describes about the power management steps taken to 
> save
> +power in that idle state and also whether its impact is 
> thread/core/quad
> +domain.
> 
>  For example:
> 
> @@ -17,6 +21,7 @@ For example:
> 
>    power-mgt {
>      ibm,cpu-idle-state-names = "nap", "fastsleep_", "winkle";
> +    ibm,cpu-idle-state-descs = "stop processor execution", "Core and
> L2 clock gating", "core and L3 power gating";

Hi
Can you make the description for all the states uniform start either 
starts with
small or capital letters. That makes cpupower output nicer way.

Thanks
Pridhiviraj

>      ibm,cpu-idle-state-residency-ns = <0x1 0x2 0x3>;
>      ibm,cpu-idle-state-latencies-ns = <0x1 0x2 0x3>;
>    };
> diff --git a/hw/slw.c b/hw/slw.c
> index 49bcd839..b0f6955e 100644
> --- a/hw/slw.c
> +++ b/hw/slw.c
> @@ -414,8 +414,10 @@ static bool idle_prepare_core(struct proc_chip
> *chip, struct cpu_thread *c)
> 
>  /* Define device-tree fields */
>  #define MAX_NAME_LEN	16
> +#define MAX_DESC_LEN	60
>  struct cpu_idle_states {
>  	char name[MAX_NAME_LEN];
> +	char desc[MAX_DESC_LEN];
>  	u32 latency_ns;
>  	u32 residency_ns;
>  	/*
> @@ -430,6 +432,7 @@ struct cpu_idle_states {
>  static struct cpu_idle_states power7_cpu_idle_states[] = {
>  	{ /* nap */
>  		.name = "nap",
> +		.desc = "stop processor execution",
>  		.latency_ns = 4000,
>  		.residency_ns = 100000,
>  		.flags = 0*OPAL_PM_DEC_STOP \
> @@ -448,6 +451,7 @@ static struct cpu_idle_states 
> power7_cpu_idle_states[] = {
>  static struct cpu_idle_states power8_cpu_idle_states[] = {
>  	{ /* nap */
>  		.name = "nap",
> +		.desc = "stop processor execution",
>  		.latency_ns = 4000,
>  		.residency_ns = 100000,
>  		.flags = 0*OPAL_PM_DEC_STOP \
> @@ -461,6 +465,7 @@ static struct cpu_idle_states 
> power8_cpu_idle_states[] = {
>  		.pm_ctrl_reg_mask = 0 },
>  	{ /* fast sleep (with workaround) */
>  		.name = "fastsleep_",
> +		.desc = "Core and L2 clock gating",
>  		.latency_ns = 40000,
>  		.residency_ns = 300000000,
>  		.flags = 1*OPAL_PM_DEC_STOP \
> @@ -475,6 +480,7 @@ static struct cpu_idle_states 
> power8_cpu_idle_states[] = {
>  		.pm_ctrl_reg_mask = OPAL_PM_SLEEP_PMICR_MASK },
>  	{ /* Winkle */
>  		.name = "winkle",
> +		.desc = "core and L3 power gating",
>  		.latency_ns = 10000000,
>  		.residency_ns = 1000000000, /* Educated guess (not measured).
>  					     * Winkle is not currently used by
> @@ -503,6 +509,7 @@ static struct cpu_idle_states 
> power8_cpu_idle_states[] = {
>  static struct cpu_idle_states power9_cpu_idle_states[] = {
>  	{
>  		.name = "stop0_lite", /* Enter stop0 with no state loss */
> +		.desc = "thread level stop instruction dispatch",
>  		.latency_ns = 1000,
>  		.residency_ns = 10000,
>  		.flags = 0*OPAL_PM_DEC_STOP \
> @@ -517,6 +524,7 @@ static struct cpu_idle_states 
> power9_cpu_idle_states[] = {
>  		.pm_ctrl_reg_mask = OPAL_PM_PSSCR_MASK },
>  	{
>  		.name = "stop0",
> +		.desc = "low latency SMT switching",
>  		.latency_ns = 2000,
>  		.residency_ns = 20000,
>  		.flags = 0*OPAL_PM_DEC_STOP \
> @@ -536,6 +544,7 @@ static struct cpu_idle_states 
> power9_cpu_idle_states[] = {
> 
>  	{
>  		.name = "stop1",
> +		.desc = "SMT switching with basic clock gating",
>  		.latency_ns = 5000,
>  		.residency_ns = 50000,
>  		.flags = 0*OPAL_PM_DEC_STOP \
> @@ -557,6 +566,7 @@ static struct cpu_idle_states 
> power9_cpu_idle_states[] = {
> 
>  	{
>  		.name = "stop2",
> +		.desc = "core level clock gating",
>  		.latency_ns = 10000,
>  		.residency_ns = 100000,
>  		.flags = 0*OPAL_PM_DEC_STOP \
> @@ -573,6 +583,7 @@ static struct cpu_idle_states 
> power9_cpu_idle_states[] = {
>  		.pm_ctrl_reg_mask = OPAL_PM_PSSCR_MASK },
>  	{
>  		.name = "stop4",
> +		.desc = "core level power gating",
>  		.latency_ns = 100000,
>  		.residency_ns = 10000000,
>  		.flags = 0*OPAL_PM_DEC_STOP \
> @@ -589,6 +600,7 @@ static struct cpu_idle_states 
> power9_cpu_idle_states[] = {
>  		.pm_ctrl_reg_mask = OPAL_PM_PSSCR_MASK },
>  	{
>  		.name = "stop5",
> +		.desc = "core level power gating and turbo boost benefit",
>  		.latency_ns = 200000,
>  		.residency_ns = 20000000,
>  		.flags = 0*OPAL_PM_DEC_STOP \
> @@ -606,6 +618,7 @@ static struct cpu_idle_states 
> power9_cpu_idle_states[] = {
> 
>  	{
>  		.name = "stop8",
> +		.desc = "core power gating and L2 clock gating",
>  		.latency_ns = 2000000,
>  		.residency_ns = 20000000,
>  		.flags = 1*OPAL_PM_DEC_STOP \
> @@ -623,6 +636,7 @@ static struct cpu_idle_states 
> power9_cpu_idle_states[] = {
> 
>  	{
>  		.name = "stop11",
> +		.desc = "quad level core and cache power gating",
>  		.latency_ns = 10000000,
>  		.residency_ns = 100000000,
>  		.flags = 1*OPAL_PM_DEC_STOP \
> @@ -647,6 +661,7 @@ static struct cpu_idle_states 
> power9_cpu_idle_states[] = {
>  static struct cpu_idle_states power9_mambo_cpu_idle_states[] = {
>  	{
>  		.name = "stop0",
> +		.desc = "low latency SMT switching",
>  		.latency_ns = 2000,
>  		.residency_ns = 20000,
>  		.flags = 0*OPAL_PM_DEC_STOP \
> @@ -663,6 +678,7 @@ static struct cpu_idle_states
> power9_mambo_cpu_idle_states[] = {
>  		.pm_ctrl_reg_mask = OPAL_PM_PSSCR_MASK },
>  	{
>  		.name = "stop1",
> +		.desc = "SMT switching with basic clock gating",
>  		.latency_ns = 5000,
>  		.residency_ns = 50000,
>  		.flags = 0*OPAL_PM_DEC_STOP \
> @@ -679,6 +695,7 @@ static struct cpu_idle_states
> power9_mambo_cpu_idle_states[] = {
>  		.pm_ctrl_reg_mask = OPAL_PM_PSSCR_MASK },
>  	{
>  		.name = "stop2",
> +		.desc = "core level clock gating",
>  		.latency_ns = 10000,
>  		.residency_ns = 100000,
>  		.flags = 0*OPAL_PM_DEC_STOP \
> @@ -695,6 +712,7 @@ static struct cpu_idle_states
> power9_mambo_cpu_idle_states[] = {
>  		.pm_ctrl_reg_mask = OPAL_PM_PSSCR_MASK },
>  	{
>  		.name = "stop4",
> +		.desc = "core level power gating",
>  		.latency_ns = 100000,
>  		.residency_ns = 1000000,
>  		.flags = 1*OPAL_PM_DEC_STOP \
> @@ -712,6 +730,7 @@ static struct cpu_idle_states
> power9_mambo_cpu_idle_states[] = {
> 
>  	{
>  		.name = "stop8",
> +		.desc = "core power gating and L2 clock gating",
>  		.latency_ns = 2000000,
>  		.residency_ns = 20000000,
>  		.flags = 1*OPAL_PM_DEC_STOP \
> @@ -729,6 +748,7 @@ static struct cpu_idle_states
> power9_mambo_cpu_idle_states[] = {
> 
>  	{
>  		.name = "stop11",
> +		.desc = "quad level core and cache power gating",
>  		.latency_ns = 10000000,
>  		.residency_ns = 100000000,
>  		.flags = 1*OPAL_PM_DEC_STOP \
> @@ -750,6 +770,7 @@ static struct cpu_idle_states
> power9_mambo_cpu_idle_states[] = {
>  static struct cpu_idle_states power9_ndd1_cpu_idle_states[] = {
>  	{
>  		.name = "stop0_lite",
> +		.desc = "thread level stop instruction dispatch",
>  		.latency_ns = 1000,
>  		.residency_ns = 10000,
>  		.flags = 0*OPAL_PM_DEC_STOP \
> @@ -764,6 +785,7 @@ static struct cpu_idle_states
> power9_ndd1_cpu_idle_states[] = {
>  		.pm_ctrl_reg_mask = OPAL_PM_PSSCR_MASK },
>  	{
>  		.name = "stop1_lite",
> +		.desc = "functional unit clock gating no SMT switching",
>  		.latency_ns = 4900,
>  		.residency_ns = 49000,
>  		.flags = 0*OPAL_PM_DEC_STOP \
> @@ -778,6 +800,7 @@ static struct cpu_idle_states
> power9_ndd1_cpu_idle_states[] = {
>  		.pm_ctrl_reg_mask = OPAL_PM_PSSCR_MASK },
>  	{
>  		.name = "stop1",
> +		.desc = "SMT switching with basic clock gating",
>  		.latency_ns = 2050000,
>  		.residency_ns = 50000,
>  		.flags = 0*OPAL_PM_DEC_STOP \
> @@ -840,10 +863,12 @@ void add_cpu_idle_state_properties(void)
> 
>  	/* Variables to track buffer length */
>  	u8 name_buf_len;
> +	u32 desc_buf_len;
>  	u8 num_supported_idle_states;
> 
>  	/* Buffers to hold idle state properties */
>  	char *name_buf, *alloced_name_buf;
> +	char *desc_buf, *alloced_desc_buf;
>  	u32 *latency_ns_buf;
>  	u32 *residency_ns_buf;
>  	u32 *flags_buf;
> @@ -949,15 +974,18 @@ void add_cpu_idle_state_properties(void)
>  	 */
> 
>  	/* Allocate memory to idle state property buffers. */
> -	alloced_name_buf= malloc(nr_states * sizeof(char) * MAX_NAME_LEN);
> +	alloced_name_buf = malloc(nr_states * sizeof(char) * MAX_NAME_LEN);
>  	name_buf = alloced_name_buf;
> +	alloced_desc_buf = malloc(nr_states * sizeof(char) * MAX_DESC_LEN);
> +	desc_buf = alloced_desc_buf;
>  	latency_ns_buf	= malloc(nr_states * sizeof(u32));
> -	residency_ns_buf= malloc(nr_states * sizeof(u32));
> -	flags_buf	= malloc(nr_states * sizeof(u32));
> -	pm_ctrl_reg_val_buf	= malloc(nr_states * sizeof(u64));
> -	pm_ctrl_reg_mask_buf	= malloc(nr_states * sizeof(u64));
> +	residency_ns_buf = malloc(nr_states * sizeof(u32));
> +	flags_buf = malloc(nr_states * sizeof(u32));
> +	pm_ctrl_reg_val_buf = malloc(nr_states * sizeof(u64));
> +	pm_ctrl_reg_mask_buf = malloc(nr_states * sizeof(u64));
> 
>  	name_buf_len = 0;
> +	desc_buf_len = 0;
>  	num_supported_idle_states = 0;
> 
>  	/*
> @@ -1021,6 +1049,9 @@ void add_cpu_idle_state_properties(void)
>  		strncpy(name_buf, states[i].name, MAX_NAME_LEN);
>  		name_buf = name_buf + strlen(states[i].name) + 1;
> 
> +		strncpy(desc_buf, states[i].desc, MAX_DESC_LEN);
> +		desc_buf = desc_buf + strlen(states[i].desc) + 1;
> +
>  		*latency_ns_buf = cpu_to_fdt32(states[i].latency_ns);
>  		latency_ns_buf++;
> 
> @@ -1038,12 +1069,14 @@ void add_cpu_idle_state_properties(void)
> 
>  		/* Increment buffer length trackers */
>  		name_buf_len += strlen(states[i].name) + 1;
> +		desc_buf_len += strlen(states[i].name) + 1;
>  		num_supported_idle_states++;
> 
>  	}
> 
>  	/* Point buffer pointers back to beginning of the buffer */
>  	name_buf -= name_buf_len;
> +	desc_buf -= desc_buf_len;
>  	latency_ns_buf -= num_supported_idle_states;
>  	residency_ns_buf -= num_supported_idle_states;
>  	flags_buf -= num_supported_idle_states;
> @@ -1051,7 +1084,9 @@ void add_cpu_idle_state_properties(void)
>  	pm_ctrl_reg_mask_buf -= num_supported_idle_states;
>  	/* Create dt properties with the buffer content */
>  	dt_add_property(power_mgt, "ibm,cpu-idle-state-names", name_buf,
> -			name_buf_len* sizeof(char));
> +			name_buf_len * sizeof(char));
> +	dt_add_property(power_mgt, "ibm,cpu-idle-state-descs", desc_buf,
> +			desc_buf_len * sizeof(char));
>  	dt_add_property(power_mgt, "ibm,cpu-idle-state-latencies-ns",
>  			latency_ns_buf, num_supported_idle_states * sizeof(u32));
>  	dt_add_property(power_mgt, "ibm,cpu-idle-state-residency-ns",
> @@ -1075,7 +1110,9 @@ void add_cpu_idle_state_properties(void)
>  				num_supported_idle_states * sizeof(u64));
>  	}
>  	assert(alloced_name_buf == name_buf);
> +	assert(alloced_desc_buf == desc_buf);
>  	free(alloced_name_buf);
> +	free(alloced_desc_buf);
>  	free(latency_ns_buf);
>  	free(residency_ns_buf);
>  	free(flags_buf);
Abhishek Goel June 5, 2018, 8:44 a.m. | #2
On 06/04/2018 02:19 PM, ppaidipe wrote:
> On 2018-06-04 13:35, Abhishek Goel wrote:
>> This patch adds description for every cpuidle state and expose it
>> through device tree. Up until now, name was being used for description
>> as no description was provided for cpuidle states.
>> The description for idle states in case of POWER can be printed
>> using "cpupower monitor -l" or "cpupower idle-info".
>>
>> Signed-off-by: Abhishek Goel <huntbag@linux.vnet.ibm.com>
>> ---
>>  doc/device-tree/ibm,opal/power-mgt.rst |  5 ++++
>>  hw/slw.c                               | 49 
>> +++++++++++++++++++++++++++++-----
>>  2 files changed, 48 insertions(+), 6 deletions(-)
>>
>> diff --git a/doc/device-tree/ibm,opal/power-mgt.rst
>> b/doc/device-tree/ibm,opal/power-mgt.rst
>> index b326a24b..598f8651 100644
>> --- a/doc/device-tree/ibm,opal/power-mgt.rst
>> +++ b/doc/device-tree/ibm,opal/power-mgt.rst
>> @@ -10,6 +10,10 @@ ibm,opal/power-mgt device tree entries
>>
>>
>>  All available CPU idle states are listed in ibm,cpu-idle-state-names
>> +The description field for cpuidle states describes the impact of that
>> +idle state. It describes about the power management steps taken to save
>> +power in that idle state and also whether its impact is 
>> thread/core/quad
>> +domain.
>>
>>  For example:
>>
>> @@ -17,6 +21,7 @@ For example:
>>
>>    power-mgt {
>>      ibm,cpu-idle-state-names = "nap", "fastsleep_", "winkle";
>> +    ibm,cpu-idle-state-descs = "stop processor execution", "Core and
>> L2 clock gating", "core and L3 power gating";
>
> Hi
> Can you make the description for all the states uniform start either 
> starts with
> small or capital letters. That makes cpupower output nicer way.
>
> Thanks
> Pridhiviraj
>
Will change the description for fastsleep.

Thanks
Abhishek
>>      ibm,cpu-idle-state-residency-ns = <0x1 0x2 0x3>;
>>      ibm,cpu-idle-state-latencies-ns = <0x1 0x2 0x3>;
>>    };
>> diff --git a/hw/slw.c b/hw/slw.c
>> index 49bcd839..b0f6955e 100644
>> --- a/hw/slw.c
>> +++ b/hw/slw.c
>> @@ -414,8 +414,10 @@ static bool idle_prepare_core(struct proc_chip
>> *chip, struct cpu_thread *c)
>>
>>  /* Define device-tree fields */
>>  #define MAX_NAME_LEN    16
>> +#define MAX_DESC_LEN    60
>>  struct cpu_idle_states {
>>      char name[MAX_NAME_LEN];
>> +    char desc[MAX_DESC_LEN];
>>      u32 latency_ns;
>>      u32 residency_ns;
>>      /*
>> @@ -430,6 +432,7 @@ struct cpu_idle_states {
>>  static struct cpu_idle_states power7_cpu_idle_states[] = {
>>      { /* nap */
>>          .name = "nap",
>> +        .desc = "stop processor execution",
>>          .latency_ns = 4000,
>>          .residency_ns = 100000,
>>          .flags = 0*OPAL_PM_DEC_STOP \
>> @@ -448,6 +451,7 @@ static struct cpu_idle_states 
>> power7_cpu_idle_states[] = {
>>  static struct cpu_idle_states power8_cpu_idle_states[] = {
>>      { /* nap */
>>          .name = "nap",
>> +        .desc = "stop processor execution",
>>          .latency_ns = 4000,
>>          .residency_ns = 100000,
>>          .flags = 0*OPAL_PM_DEC_STOP \
>> @@ -461,6 +465,7 @@ static struct cpu_idle_states 
>> power8_cpu_idle_states[] = {
>>          .pm_ctrl_reg_mask = 0 },
>>      { /* fast sleep (with workaround) */
>>          .name = "fastsleep_",
>> +        .desc = "Core and L2 clock gating",
>>          .latency_ns = 40000,
>>          .residency_ns = 300000000,
>>          .flags = 1*OPAL_PM_DEC_STOP \
>> @@ -475,6 +480,7 @@ static struct cpu_idle_states 
>> power8_cpu_idle_states[] = {
>>          .pm_ctrl_reg_mask = OPAL_PM_SLEEP_PMICR_MASK },
>>      { /* Winkle */
>>          .name = "winkle",
>> +        .desc = "core and L3 power gating",
>>          .latency_ns = 10000000,
>>          .residency_ns = 1000000000, /* Educated guess (not measured).
>>                           * Winkle is not currently used by
>> @@ -503,6 +509,7 @@ static struct cpu_idle_states 
>> power8_cpu_idle_states[] = {
>>  static struct cpu_idle_states power9_cpu_idle_states[] = {
>>      {
>>          .name = "stop0_lite", /* Enter stop0 with no state loss */
>> +        .desc = "thread level stop instruction dispatch",
>>          .latency_ns = 1000,
>>          .residency_ns = 10000,
>>          .flags = 0*OPAL_PM_DEC_STOP \
>> @@ -517,6 +524,7 @@ static struct cpu_idle_states 
>> power9_cpu_idle_states[] = {
>>          .pm_ctrl_reg_mask = OPAL_PM_PSSCR_MASK },
>>      {
>>          .name = "stop0",
>> +        .desc = "low latency SMT switching",
>>          .latency_ns = 2000,
>>          .residency_ns = 20000,
>>          .flags = 0*OPAL_PM_DEC_STOP \
>> @@ -536,6 +544,7 @@ static struct cpu_idle_states 
>> power9_cpu_idle_states[] = {
>>
>>      {
>>          .name = "stop1",
>> +        .desc = "SMT switching with basic clock gating",
>>          .latency_ns = 5000,
>>          .residency_ns = 50000,
>>          .flags = 0*OPAL_PM_DEC_STOP \
>> @@ -557,6 +566,7 @@ static struct cpu_idle_states 
>> power9_cpu_idle_states[] = {
>>
>>      {
>>          .name = "stop2",
>> +        .desc = "core level clock gating",
>>          .latency_ns = 10000,
>>          .residency_ns = 100000,
>>          .flags = 0*OPAL_PM_DEC_STOP \
>> @@ -573,6 +583,7 @@ static struct cpu_idle_states 
>> power9_cpu_idle_states[] = {
>>          .pm_ctrl_reg_mask = OPAL_PM_PSSCR_MASK },
>>      {
>>          .name = "stop4",
>> +        .desc = "core level power gating",
>>          .latency_ns = 100000,
>>          .residency_ns = 10000000,
>>          .flags = 0*OPAL_PM_DEC_STOP \
>> @@ -589,6 +600,7 @@ static struct cpu_idle_states 
>> power9_cpu_idle_states[] = {
>>          .pm_ctrl_reg_mask = OPAL_PM_PSSCR_MASK },
>>      {
>>          .name = "stop5",
>> +        .desc = "core level power gating and turbo boost benefit",
>>          .latency_ns = 200000,
>>          .residency_ns = 20000000,
>>          .flags = 0*OPAL_PM_DEC_STOP \
>> @@ -606,6 +618,7 @@ static struct cpu_idle_states 
>> power9_cpu_idle_states[] = {
>>
>>      {
>>          .name = "stop8",
>> +        .desc = "core power gating and L2 clock gating",
>>          .latency_ns = 2000000,
>>          .residency_ns = 20000000,
>>          .flags = 1*OPAL_PM_DEC_STOP \
>> @@ -623,6 +636,7 @@ static struct cpu_idle_states 
>> power9_cpu_idle_states[] = {
>>
>>      {
>>          .name = "stop11",
>> +        .desc = "quad level core and cache power gating",
>>          .latency_ns = 10000000,
>>          .residency_ns = 100000000,
>>          .flags = 1*OPAL_PM_DEC_STOP \
>> @@ -647,6 +661,7 @@ static struct cpu_idle_states 
>> power9_cpu_idle_states[] = {
>>  static struct cpu_idle_states power9_mambo_cpu_idle_states[] = {
>>      {
>>          .name = "stop0",
>> +        .desc = "low latency SMT switching",
>>          .latency_ns = 2000,
>>          .residency_ns = 20000,
>>          .flags = 0*OPAL_PM_DEC_STOP \
>> @@ -663,6 +678,7 @@ static struct cpu_idle_states
>> power9_mambo_cpu_idle_states[] = {
>>          .pm_ctrl_reg_mask = OPAL_PM_PSSCR_MASK },
>>      {
>>          .name = "stop1",
>> +        .desc = "SMT switching with basic clock gating",
>>          .latency_ns = 5000,
>>          .residency_ns = 50000,
>>          .flags = 0*OPAL_PM_DEC_STOP \
>> @@ -679,6 +695,7 @@ static struct cpu_idle_states
>> power9_mambo_cpu_idle_states[] = {
>>          .pm_ctrl_reg_mask = OPAL_PM_PSSCR_MASK },
>>      {
>>          .name = "stop2",
>> +        .desc = "core level clock gating",
>>          .latency_ns = 10000,
>>          .residency_ns = 100000,
>>          .flags = 0*OPAL_PM_DEC_STOP \
>> @@ -695,6 +712,7 @@ static struct cpu_idle_states
>> power9_mambo_cpu_idle_states[] = {
>>          .pm_ctrl_reg_mask = OPAL_PM_PSSCR_MASK },
>>      {
>>          .name = "stop4",
>> +        .desc = "core level power gating",
>>          .latency_ns = 100000,
>>          .residency_ns = 1000000,
>>          .flags = 1*OPAL_PM_DEC_STOP \
>> @@ -712,6 +730,7 @@ static struct cpu_idle_states
>> power9_mambo_cpu_idle_states[] = {
>>
>>      {
>>          .name = "stop8",
>> +        .desc = "core power gating and L2 clock gating",
>>          .latency_ns = 2000000,
>>          .residency_ns = 20000000,
>>          .flags = 1*OPAL_PM_DEC_STOP \
>> @@ -729,6 +748,7 @@ static struct cpu_idle_states
>> power9_mambo_cpu_idle_states[] = {
>>
>>      {
>>          .name = "stop11",
>> +        .desc = "quad level core and cache power gating",
>>          .latency_ns = 10000000,
>>          .residency_ns = 100000000,
>>          .flags = 1*OPAL_PM_DEC_STOP \
>> @@ -750,6 +770,7 @@ static struct cpu_idle_states
>> power9_mambo_cpu_idle_states[] = {
>>  static struct cpu_idle_states power9_ndd1_cpu_idle_states[] = {
>>      {
>>          .name = "stop0_lite",
>> +        .desc = "thread level stop instruction dispatch",
>>          .latency_ns = 1000,
>>          .residency_ns = 10000,
>>          .flags = 0*OPAL_PM_DEC_STOP \
>> @@ -764,6 +785,7 @@ static struct cpu_idle_states
>> power9_ndd1_cpu_idle_states[] = {
>>          .pm_ctrl_reg_mask = OPAL_PM_PSSCR_MASK },
>>      {
>>          .name = "stop1_lite",
>> +        .desc = "functional unit clock gating no SMT switching",
>>          .latency_ns = 4900,
>>          .residency_ns = 49000,
>>          .flags = 0*OPAL_PM_DEC_STOP \
>> @@ -778,6 +800,7 @@ static struct cpu_idle_states
>> power9_ndd1_cpu_idle_states[] = {
>>          .pm_ctrl_reg_mask = OPAL_PM_PSSCR_MASK },
>>      {
>>          .name = "stop1",
>> +        .desc = "SMT switching with basic clock gating",
>>          .latency_ns = 2050000,
>>          .residency_ns = 50000,
>>          .flags = 0*OPAL_PM_DEC_STOP \
>> @@ -840,10 +863,12 @@ void add_cpu_idle_state_properties(void)
>>
>>      /* Variables to track buffer length */
>>      u8 name_buf_len;
>> +    u32 desc_buf_len;
>>      u8 num_supported_idle_states;
>>
>>      /* Buffers to hold idle state properties */
>>      char *name_buf, *alloced_name_buf;
>> +    char *desc_buf, *alloced_desc_buf;
>>      u32 *latency_ns_buf;
>>      u32 *residency_ns_buf;
>>      u32 *flags_buf;
>> @@ -949,15 +974,18 @@ void add_cpu_idle_state_properties(void)
>>       */
>>
>>      /* Allocate memory to idle state property buffers. */
>> -    alloced_name_buf= malloc(nr_states * sizeof(char) * MAX_NAME_LEN);
>> +    alloced_name_buf = malloc(nr_states * sizeof(char) * MAX_NAME_LEN);
>>      name_buf = alloced_name_buf;
>> +    alloced_desc_buf = malloc(nr_states * sizeof(char) * MAX_DESC_LEN);
>> +    desc_buf = alloced_desc_buf;
>>      latency_ns_buf    = malloc(nr_states * sizeof(u32));
>> -    residency_ns_buf= malloc(nr_states * sizeof(u32));
>> -    flags_buf    = malloc(nr_states * sizeof(u32));
>> -    pm_ctrl_reg_val_buf    = malloc(nr_states * sizeof(u64));
>> -    pm_ctrl_reg_mask_buf    = malloc(nr_states * sizeof(u64));
>> +    residency_ns_buf = malloc(nr_states * sizeof(u32));
>> +    flags_buf = malloc(nr_states * sizeof(u32));
>> +    pm_ctrl_reg_val_buf = malloc(nr_states * sizeof(u64));
>> +    pm_ctrl_reg_mask_buf = malloc(nr_states * sizeof(u64));
>>
>>      name_buf_len = 0;
>> +    desc_buf_len = 0;
>>      num_supported_idle_states = 0;
>>
>>      /*
>> @@ -1021,6 +1049,9 @@ void add_cpu_idle_state_properties(void)
>>          strncpy(name_buf, states[i].name, MAX_NAME_LEN);
>>          name_buf = name_buf + strlen(states[i].name) + 1;
>>
>> +        strncpy(desc_buf, states[i].desc, MAX_DESC_LEN);
>> +        desc_buf = desc_buf + strlen(states[i].desc) + 1;
>> +
>>          *latency_ns_buf = cpu_to_fdt32(states[i].latency_ns);
>>          latency_ns_buf++;
>>
>> @@ -1038,12 +1069,14 @@ void add_cpu_idle_state_properties(void)
>>
>>          /* Increment buffer length trackers */
>>          name_buf_len += strlen(states[i].name) + 1;
>> +        desc_buf_len += strlen(states[i].name) + 1;
>>          num_supported_idle_states++;
>>
>>      }
>>
>>      /* Point buffer pointers back to beginning of the buffer */
>>      name_buf -= name_buf_len;
>> +    desc_buf -= desc_buf_len;
>>      latency_ns_buf -= num_supported_idle_states;
>>      residency_ns_buf -= num_supported_idle_states;
>>      flags_buf -= num_supported_idle_states;
>> @@ -1051,7 +1084,9 @@ void add_cpu_idle_state_properties(void)
>>      pm_ctrl_reg_mask_buf -= num_supported_idle_states;
>>      /* Create dt properties with the buffer content */
>>      dt_add_property(power_mgt, "ibm,cpu-idle-state-names", name_buf,
>> -            name_buf_len* sizeof(char));
>> +            name_buf_len * sizeof(char));
>> +    dt_add_property(power_mgt, "ibm,cpu-idle-state-descs", desc_buf,
>> +            desc_buf_len * sizeof(char));
>>      dt_add_property(power_mgt, "ibm,cpu-idle-state-latencies-ns",
>>              latency_ns_buf, num_supported_idle_states * sizeof(u32));
>>      dt_add_property(power_mgt, "ibm,cpu-idle-state-residency-ns",
>> @@ -1075,7 +1110,9 @@ void add_cpu_idle_state_properties(void)
>>                  num_supported_idle_states * sizeof(u64));
>>      }
>>      assert(alloced_name_buf == name_buf);
>> +    assert(alloced_desc_buf == desc_buf);
>>      free(alloced_name_buf);
>> +    free(alloced_desc_buf);
>>      free(latency_ns_buf);
>>      free(residency_ns_buf);
>>      free(flags_buf);

Patch

diff --git a/doc/device-tree/ibm,opal/power-mgt.rst b/doc/device-tree/ibm,opal/power-mgt.rst
index b326a24b..598f8651 100644
--- a/doc/device-tree/ibm,opal/power-mgt.rst
+++ b/doc/device-tree/ibm,opal/power-mgt.rst
@@ -10,6 +10,10 @@  ibm,opal/power-mgt device tree entries
 
 
 All available CPU idle states are listed in ibm,cpu-idle-state-names
+The description field for cpuidle states describes the impact of that
+idle state. It describes about the power management steps taken to save
+power in that idle state and also whether its impact is thread/core/quad
+domain.
 
 For example:
 
@@ -17,6 +21,7 @@  For example:
 
   power-mgt {
     ibm,cpu-idle-state-names = "nap", "fastsleep_", "winkle";
+    ibm,cpu-idle-state-descs = "stop processor execution", "Core and L2 clock gating", "core and L3 power gating";
     ibm,cpu-idle-state-residency-ns = <0x1 0x2 0x3>;
     ibm,cpu-idle-state-latencies-ns = <0x1 0x2 0x3>;
   };
diff --git a/hw/slw.c b/hw/slw.c
index 49bcd839..b0f6955e 100644
--- a/hw/slw.c
+++ b/hw/slw.c
@@ -414,8 +414,10 @@  static bool idle_prepare_core(struct proc_chip *chip, struct cpu_thread *c)
 
 /* Define device-tree fields */
 #define MAX_NAME_LEN	16
+#define MAX_DESC_LEN	60
 struct cpu_idle_states {
 	char name[MAX_NAME_LEN];
+	char desc[MAX_DESC_LEN];
 	u32 latency_ns;
 	u32 residency_ns;
 	/*
@@ -430,6 +432,7 @@  struct cpu_idle_states {
 static struct cpu_idle_states power7_cpu_idle_states[] = {
 	{ /* nap */
 		.name = "nap",
+		.desc = "stop processor execution",
 		.latency_ns = 4000,
 		.residency_ns = 100000,
 		.flags = 0*OPAL_PM_DEC_STOP \
@@ -448,6 +451,7 @@  static struct cpu_idle_states power7_cpu_idle_states[] = {
 static struct cpu_idle_states power8_cpu_idle_states[] = {
 	{ /* nap */
 		.name = "nap",
+		.desc = "stop processor execution",
 		.latency_ns = 4000,
 		.residency_ns = 100000,
 		.flags = 0*OPAL_PM_DEC_STOP \
@@ -461,6 +465,7 @@  static struct cpu_idle_states power8_cpu_idle_states[] = {
 		.pm_ctrl_reg_mask = 0 },
 	{ /* fast sleep (with workaround) */
 		.name = "fastsleep_",
+		.desc = "Core and L2 clock gating",
 		.latency_ns = 40000,
 		.residency_ns = 300000000,
 		.flags = 1*OPAL_PM_DEC_STOP \
@@ -475,6 +480,7 @@  static struct cpu_idle_states power8_cpu_idle_states[] = {
 		.pm_ctrl_reg_mask = OPAL_PM_SLEEP_PMICR_MASK },
 	{ /* Winkle */
 		.name = "winkle",
+		.desc = "core and L3 power gating",
 		.latency_ns = 10000000,
 		.residency_ns = 1000000000, /* Educated guess (not measured).
 					     * Winkle is not currently used by 
@@ -503,6 +509,7 @@  static struct cpu_idle_states power8_cpu_idle_states[] = {
 static struct cpu_idle_states power9_cpu_idle_states[] = {
 	{
 		.name = "stop0_lite", /* Enter stop0 with no state loss */
+		.desc = "thread level stop instruction dispatch",
 		.latency_ns = 1000,
 		.residency_ns = 10000,
 		.flags = 0*OPAL_PM_DEC_STOP \
@@ -517,6 +524,7 @@  static struct cpu_idle_states power9_cpu_idle_states[] = {
 		.pm_ctrl_reg_mask = OPAL_PM_PSSCR_MASK },
 	{
 		.name = "stop0",
+		.desc = "low latency SMT switching",
 		.latency_ns = 2000,
 		.residency_ns = 20000,
 		.flags = 0*OPAL_PM_DEC_STOP \
@@ -536,6 +544,7 @@  static struct cpu_idle_states power9_cpu_idle_states[] = {
 
 	{
 		.name = "stop1",
+		.desc = "SMT switching with basic clock gating",
 		.latency_ns = 5000,
 		.residency_ns = 50000,
 		.flags = 0*OPAL_PM_DEC_STOP \
@@ -557,6 +566,7 @@  static struct cpu_idle_states power9_cpu_idle_states[] = {
 
 	{
 		.name = "stop2",
+		.desc = "core level clock gating",
 		.latency_ns = 10000,
 		.residency_ns = 100000,
 		.flags = 0*OPAL_PM_DEC_STOP \
@@ -573,6 +583,7 @@  static struct cpu_idle_states power9_cpu_idle_states[] = {
 		.pm_ctrl_reg_mask = OPAL_PM_PSSCR_MASK },
 	{
 		.name = "stop4",
+		.desc = "core level power gating",
 		.latency_ns = 100000,
 		.residency_ns = 10000000,
 		.flags = 0*OPAL_PM_DEC_STOP \
@@ -589,6 +600,7 @@  static struct cpu_idle_states power9_cpu_idle_states[] = {
 		.pm_ctrl_reg_mask = OPAL_PM_PSSCR_MASK },
 	{
 		.name = "stop5",
+		.desc = "core level power gating and turbo boost benefit",
 		.latency_ns = 200000,
 		.residency_ns = 20000000,
 		.flags = 0*OPAL_PM_DEC_STOP \
@@ -606,6 +618,7 @@  static struct cpu_idle_states power9_cpu_idle_states[] = {
 
 	{
 		.name = "stop8",
+		.desc = "core power gating and L2 clock gating",
 		.latency_ns = 2000000,
 		.residency_ns = 20000000,
 		.flags = 1*OPAL_PM_DEC_STOP \
@@ -623,6 +636,7 @@  static struct cpu_idle_states power9_cpu_idle_states[] = {
 
 	{
 		.name = "stop11",
+		.desc = "quad level core and cache power gating",
 		.latency_ns = 10000000,
 		.residency_ns = 100000000,
 		.flags = 1*OPAL_PM_DEC_STOP \
@@ -647,6 +661,7 @@  static struct cpu_idle_states power9_cpu_idle_states[] = {
 static struct cpu_idle_states power9_mambo_cpu_idle_states[] = {
 	{
 		.name = "stop0",
+		.desc = "low latency SMT switching",
 		.latency_ns = 2000,
 		.residency_ns = 20000,
 		.flags = 0*OPAL_PM_DEC_STOP \
@@ -663,6 +678,7 @@  static struct cpu_idle_states power9_mambo_cpu_idle_states[] = {
 		.pm_ctrl_reg_mask = OPAL_PM_PSSCR_MASK },
 	{
 		.name = "stop1",
+		.desc = "SMT switching with basic clock gating",
 		.latency_ns = 5000,
 		.residency_ns = 50000,
 		.flags = 0*OPAL_PM_DEC_STOP \
@@ -679,6 +695,7 @@  static struct cpu_idle_states power9_mambo_cpu_idle_states[] = {
 		.pm_ctrl_reg_mask = OPAL_PM_PSSCR_MASK },
 	{
 		.name = "stop2",
+		.desc = "core level clock gating",
 		.latency_ns = 10000,
 		.residency_ns = 100000,
 		.flags = 0*OPAL_PM_DEC_STOP \
@@ -695,6 +712,7 @@  static struct cpu_idle_states power9_mambo_cpu_idle_states[] = {
 		.pm_ctrl_reg_mask = OPAL_PM_PSSCR_MASK },
 	{
 		.name = "stop4",
+		.desc = "core level power gating",
 		.latency_ns = 100000,
 		.residency_ns = 1000000,
 		.flags = 1*OPAL_PM_DEC_STOP \
@@ -712,6 +730,7 @@  static struct cpu_idle_states power9_mambo_cpu_idle_states[] = {
 
 	{
 		.name = "stop8",
+		.desc = "core power gating and L2 clock gating",
 		.latency_ns = 2000000,
 		.residency_ns = 20000000,
 		.flags = 1*OPAL_PM_DEC_STOP \
@@ -729,6 +748,7 @@  static struct cpu_idle_states power9_mambo_cpu_idle_states[] = {
 
 	{
 		.name = "stop11",
+		.desc = "quad level core and cache power gating",
 		.latency_ns = 10000000,
 		.residency_ns = 100000000,
 		.flags = 1*OPAL_PM_DEC_STOP \
@@ -750,6 +770,7 @@  static struct cpu_idle_states power9_mambo_cpu_idle_states[] = {
 static struct cpu_idle_states power9_ndd1_cpu_idle_states[] = {
 	{
 		.name = "stop0_lite",
+		.desc = "thread level stop instruction dispatch",
 		.latency_ns = 1000,
 		.residency_ns = 10000,
 		.flags = 0*OPAL_PM_DEC_STOP \
@@ -764,6 +785,7 @@  static struct cpu_idle_states power9_ndd1_cpu_idle_states[] = {
 		.pm_ctrl_reg_mask = OPAL_PM_PSSCR_MASK },
 	{
 		.name = "stop1_lite",
+		.desc = "functional unit clock gating no SMT switching",
 		.latency_ns = 4900,
 		.residency_ns = 49000,
 		.flags = 0*OPAL_PM_DEC_STOP \
@@ -778,6 +800,7 @@  static struct cpu_idle_states power9_ndd1_cpu_idle_states[] = {
 		.pm_ctrl_reg_mask = OPAL_PM_PSSCR_MASK },
 	{
 		.name = "stop1",
+		.desc = "SMT switching with basic clock gating",
 		.latency_ns = 2050000,
 		.residency_ns = 50000,
 		.flags = 0*OPAL_PM_DEC_STOP \
@@ -840,10 +863,12 @@  void add_cpu_idle_state_properties(void)
 
 	/* Variables to track buffer length */
 	u8 name_buf_len;
+	u32 desc_buf_len;
 	u8 num_supported_idle_states;
 
 	/* Buffers to hold idle state properties */
 	char *name_buf, *alloced_name_buf;
+	char *desc_buf, *alloced_desc_buf;
 	u32 *latency_ns_buf;
 	u32 *residency_ns_buf;
 	u32 *flags_buf;
@@ -949,15 +974,18 @@  void add_cpu_idle_state_properties(void)
 	 */
 
 	/* Allocate memory to idle state property buffers. */
-	alloced_name_buf= malloc(nr_states * sizeof(char) * MAX_NAME_LEN);
+	alloced_name_buf = malloc(nr_states * sizeof(char) * MAX_NAME_LEN);
 	name_buf = alloced_name_buf;
+	alloced_desc_buf = malloc(nr_states * sizeof(char) * MAX_DESC_LEN);
+	desc_buf = alloced_desc_buf;
 	latency_ns_buf	= malloc(nr_states * sizeof(u32));
-	residency_ns_buf= malloc(nr_states * sizeof(u32));
-	flags_buf	= malloc(nr_states * sizeof(u32));
-	pm_ctrl_reg_val_buf	= malloc(nr_states * sizeof(u64));
-	pm_ctrl_reg_mask_buf	= malloc(nr_states * sizeof(u64));
+	residency_ns_buf = malloc(nr_states * sizeof(u32));
+	flags_buf = malloc(nr_states * sizeof(u32));
+	pm_ctrl_reg_val_buf = malloc(nr_states * sizeof(u64));
+	pm_ctrl_reg_mask_buf = malloc(nr_states * sizeof(u64));
 
 	name_buf_len = 0;
+	desc_buf_len = 0;
 	num_supported_idle_states = 0;
 
 	/*
@@ -1021,6 +1049,9 @@  void add_cpu_idle_state_properties(void)
 		strncpy(name_buf, states[i].name, MAX_NAME_LEN);
 		name_buf = name_buf + strlen(states[i].name) + 1;
 
+		strncpy(desc_buf, states[i].desc, MAX_DESC_LEN);
+		desc_buf = desc_buf + strlen(states[i].desc) + 1;
+
 		*latency_ns_buf = cpu_to_fdt32(states[i].latency_ns);
 		latency_ns_buf++;
 
@@ -1038,12 +1069,14 @@  void add_cpu_idle_state_properties(void)
 
 		/* Increment buffer length trackers */
 		name_buf_len += strlen(states[i].name) + 1;
+		desc_buf_len += strlen(states[i].name) + 1;
 		num_supported_idle_states++;
 
 	}
 
 	/* Point buffer pointers back to beginning of the buffer */
 	name_buf -= name_buf_len;
+	desc_buf -= desc_buf_len;
 	latency_ns_buf -= num_supported_idle_states;
 	residency_ns_buf -= num_supported_idle_states;
 	flags_buf -= num_supported_idle_states;
@@ -1051,7 +1084,9 @@  void add_cpu_idle_state_properties(void)
 	pm_ctrl_reg_mask_buf -= num_supported_idle_states;
 	/* Create dt properties with the buffer content */
 	dt_add_property(power_mgt, "ibm,cpu-idle-state-names", name_buf,
-			name_buf_len* sizeof(char));
+			name_buf_len * sizeof(char));
+	dt_add_property(power_mgt, "ibm,cpu-idle-state-descs", desc_buf,
+			desc_buf_len * sizeof(char));
 	dt_add_property(power_mgt, "ibm,cpu-idle-state-latencies-ns",
 			latency_ns_buf, num_supported_idle_states * sizeof(u32));
 	dt_add_property(power_mgt, "ibm,cpu-idle-state-residency-ns",
@@ -1075,7 +1110,9 @@  void add_cpu_idle_state_properties(void)
 				num_supported_idle_states * sizeof(u64));
 	}
 	assert(alloced_name_buf == name_buf);
+	assert(alloced_desc_buf == desc_buf);
 	free(alloced_name_buf);
+	free(alloced_desc_buf);
 	free(latency_ns_buf);
 	free(residency_ns_buf);
 	free(flags_buf);