* [PATCH 0/3] Enable substate residencies for multiple PMCs
@ 2025-12-17 0:23 Xi Pardee
2025-12-17 0:23 ` [PATCH 1/3] platform/x86/intel/pmc: Change LPM mode fields to u8 Xi Pardee
` (2 more replies)
0 siblings, 3 replies; 8+ messages in thread
From: Xi Pardee @ 2025-12-17 0:23 UTC (permalink / raw)
To: xi.pardee, irenic.rajneesh, david.e.box, hdegoede, ilpo.jarvinen,
platform-driver-x86, linux-kernel, linux-pm
This patch series enables substate residencies for multiple PMCs.
The first two patches prepare this change:
- The first patch changes the datatype of LPM mode attributes to u8.
- The second patch moves the LPM mode attributes from the pmc_dev to
the pmc struture.
The final patch enables the substate residencies for multiple PMCs.
Xi Pardee (3):
platform/x86/intel/pmc: Change LPM mode fields to u8
platform/x86/intel/pmc: Move LPM mode attributes to PMC
platform/x86/intel/pmc: Enable substate residencies for multiple PMCs
drivers/platform/x86/intel/pmc/core.c | 79 ++++++++++++++++++---------
drivers/platform/x86/intel/pmc/core.h | 15 +++--
2 files changed, 60 insertions(+), 34 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH 1/3] platform/x86/intel/pmc: Change LPM mode fields to u8 2025-12-17 0:23 [PATCH 0/3] Enable substate residencies for multiple PMCs Xi Pardee @ 2025-12-17 0:23 ` Xi Pardee 2025-12-23 12:29 ` Ilpo Järvinen 2025-12-17 0:23 ` [PATCH 2/3] platform/x86/intel/pmc: Move LPM mode attributes to PMC Xi Pardee 2025-12-17 0:23 ` [PATCH 3/3] platform/x86/intel/pmc: Enable substate residencies for multiple PMCs Xi Pardee 2 siblings, 1 reply; 8+ messages in thread From: Xi Pardee @ 2025-12-17 0:23 UTC (permalink / raw) To: xi.pardee, irenic.rajneesh, david.e.box, hdegoede, ilpo.jarvinen, platform-driver-x86, linux-kernel, linux-pm Change the datatypes pf num_lpm_modes and lpm_en_modes[] from int to u8. The u8 type is more appropriate and improves the readability and maintainability of the code. Signed-off-by: Xi Pardee <xi.pardee@linux.intel.com> --- drivers/platform/x86/intel/pmc/core.c | 18 ++++++++++-------- drivers/platform/x86/intel/pmc/core.h | 4 ++-- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/platform/x86/intel/pmc/core.c b/drivers/platform/x86/intel/pmc/core.c index 7d7ae8a40b0ec..3e916228e7ed2 100644 --- a/drivers/platform/x86/intel/pmc/core.c +++ b/drivers/platform/x86/intel/pmc/core.c @@ -779,7 +779,7 @@ static int pmc_core_substate_res_show(struct seq_file *s, void *unused) struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; const int lpm_adj_x2 = pmc->map->lpm_res_counter_step_x2; u32 offset = pmc->map->lpm_residency_offset; - int mode; + u8 mode; seq_printf(s, "%-10s %-15s\n", "Substate", "Residency"); @@ -838,7 +838,7 @@ static void pmc_core_substate_req_header_show(struct seq_file *s, int pmc_index, enum header_type type) { struct pmc_dev *pmcdev = s->private; - int mode; + u8 mode; seq_printf(s, "%40s |", "Element"); pmc_for_each_mode(mode, pmcdev) @@ -880,7 +880,7 @@ static int pmc_core_substate_blk_req_show(struct seq_file *s, void *unused) const struct pmc_bit_map *map; for (map = maps[r_idx]; map->name; map++) { - int mode; + u8 mode; if (!map->blk) continue; @@ -953,7 +953,8 @@ static int pmc_core_substate_req_regs_show(struct seq_file *s, void *unused) u32 lpm_status; u32 lpm_status_live; const struct pmc_bit_map *map; - int mode, i, len = 32; + int i, len = 32; + u8 mode; /* * Capture the requirements and create a mask so that we only @@ -1065,7 +1066,7 @@ static int pmc_core_lpm_latch_mode_show(struct seq_file *s, void *unused) struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; bool c10; u32 reg; - int mode; + u8 mode; reg = pmc_core_reg_read(pmc, pmc->map->lpm_sts_latch_en_offset); if (reg & LPM_STS_LATCH_MODE) { @@ -1097,8 +1098,9 @@ static ssize_t pmc_core_lpm_latch_mode_write(struct file *file, struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; bool clear = false, c10 = false; unsigned char buf[8]; - int m, mode; + int mode; u32 reg; + u8 m; if (count > sizeof(buf) - 1) return -EINVAL; @@ -1490,8 +1492,8 @@ int pmc_core_pmt_get_lpm_req(struct pmc_dev *pmcdev, struct pmc *pmc, struct tel { const u8 *lpm_indices; int num_maps, mode_offset = 0; - int ret, mode; - int lpm_size; + int ret, lpm_size; + u8 mode; lpm_indices = pmc->map->lpm_reg_index; num_maps = pmc->map->lpm_num_maps; diff --git a/drivers/platform/x86/intel/pmc/core.h b/drivers/platform/x86/intel/pmc/core.h index 272fb4f57f346..ead2f33ed3ed5 100644 --- a/drivers/platform/x86/intel/pmc/core.h +++ b/drivers/platform/x86/intel/pmc/core.h @@ -462,8 +462,8 @@ struct pmc_dev { struct mutex lock; /* generic mutex lock for PMC Core */ u64 s0ix_counter; - int num_lpm_modes; - int lpm_en_modes[LPM_MAX_NUM_MODES]; + u8 num_lpm_modes; + u8 lpm_en_modes[LPM_MAX_NUM_MODES]; void (*suspend)(struct pmc_dev *pmcdev); int (*resume)(struct pmc_dev *pmcdev); -- 2.43.0 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 1/3] platform/x86/intel/pmc: Change LPM mode fields to u8 2025-12-17 0:23 ` [PATCH 1/3] platform/x86/intel/pmc: Change LPM mode fields to u8 Xi Pardee @ 2025-12-23 12:29 ` Ilpo Järvinen 2026-01-06 23:45 ` Xi Pardee 0 siblings, 1 reply; 8+ messages in thread From: Ilpo Järvinen @ 2025-12-23 12:29 UTC (permalink / raw) To: Xi Pardee Cc: irenic.rajneesh, david.e.box, hdegoede, platform-driver-x86, LKML, linux-pm On Tue, 16 Dec 2025, Xi Pardee wrote: > Change the datatypes pf num_lpm_modes and lpm_en_modes[] from int > to u8. The u8 type is more appropriate and improves the readability > and maintainability of the code. > > Signed-off-by: Xi Pardee <xi.pardee@linux.intel.com> > --- > drivers/platform/x86/intel/pmc/core.c | 18 ++++++++++-------- > drivers/platform/x86/intel/pmc/core.h | 4 ++-- > 2 files changed, 12 insertions(+), 10 deletions(-) > > diff --git a/drivers/platform/x86/intel/pmc/core.c b/drivers/platform/x86/intel/pmc/core.c > index 7d7ae8a40b0ec..3e916228e7ed2 100644 > --- a/drivers/platform/x86/intel/pmc/core.c > +++ b/drivers/platform/x86/intel/pmc/core.c > @@ -779,7 +779,7 @@ static int pmc_core_substate_res_show(struct seq_file *s, void *unused) > struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; > const int lpm_adj_x2 = pmc->map->lpm_res_counter_step_x2; > u32 offset = pmc->map->lpm_residency_offset; > - int mode; > + u8 mode; > > seq_printf(s, "%-10s %-15s\n", "Substate", "Residency"); > > @@ -838,7 +838,7 @@ static void pmc_core_substate_req_header_show(struct seq_file *s, int pmc_index, > enum header_type type) > { > struct pmc_dev *pmcdev = s->private; > - int mode; > + u8 mode; > > seq_printf(s, "%40s |", "Element"); > pmc_for_each_mode(mode, pmcdev) > @@ -880,7 +880,7 @@ static int pmc_core_substate_blk_req_show(struct seq_file *s, void *unused) > const struct pmc_bit_map *map; > > for (map = maps[r_idx]; map->name; map++) { > - int mode; > + u8 mode; > > if (!map->blk) > continue; > @@ -953,7 +953,8 @@ static int pmc_core_substate_req_regs_show(struct seq_file *s, void *unused) > u32 lpm_status; > u32 lpm_status_live; > const struct pmc_bit_map *map; > - int mode, i, len = 32; > + int i, len = 32; > + u8 mode; > > /* > * Capture the requirements and create a mask so that we only > @@ -1065,7 +1066,7 @@ static int pmc_core_lpm_latch_mode_show(struct seq_file *s, void *unused) > struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; > bool c10; > u32 reg; > - int mode; > + u8 mode; > > reg = pmc_core_reg_read(pmc, pmc->map->lpm_sts_latch_en_offset); > if (reg & LPM_STS_LATCH_MODE) { > @@ -1097,8 +1098,9 @@ static ssize_t pmc_core_lpm_latch_mode_write(struct file *file, > struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; > bool clear = false, c10 = false; > unsigned char buf[8]; > - int m, mode; > + int mode; > u32 reg; > + u8 m; > > if (count > sizeof(buf) - 1) > return -EINVAL; > @@ -1490,8 +1492,8 @@ int pmc_core_pmt_get_lpm_req(struct pmc_dev *pmcdev, struct pmc *pmc, struct tel > { > const u8 *lpm_indices; > int num_maps, mode_offset = 0; > - int ret, mode; > - int lpm_size; > + int ret, lpm_size; > + u8 mode; > > lpm_indices = pmc->map->lpm_reg_index; > num_maps = pmc->map->lpm_num_maps; Why is "mode" in pmc_core_get_low_power_modes() left untouched? (Unrelated to the patch, it seems to contain a double empty line as well.) > diff --git a/drivers/platform/x86/intel/pmc/core.h b/drivers/platform/x86/intel/pmc/core.h > index 272fb4f57f346..ead2f33ed3ed5 100644 > --- a/drivers/platform/x86/intel/pmc/core.h > +++ b/drivers/platform/x86/intel/pmc/core.h > @@ -462,8 +462,8 @@ struct pmc_dev { > struct mutex lock; /* generic mutex lock for PMC Core */ > > u64 s0ix_counter; > - int num_lpm_modes; > - int lpm_en_modes[LPM_MAX_NUM_MODES]; > + u8 num_lpm_modes; > + u8 lpm_en_modes[LPM_MAX_NUM_MODES]; > void (*suspend)(struct pmc_dev *pmcdev); > int (*resume)(struct pmc_dev *pmcdev); > > -- i. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/3] platform/x86/intel/pmc: Change LPM mode fields to u8 2025-12-23 12:29 ` Ilpo Järvinen @ 2026-01-06 23:45 ` Xi Pardee 0 siblings, 0 replies; 8+ messages in thread From: Xi Pardee @ 2026-01-06 23:45 UTC (permalink / raw) To: Ilpo Järvinen Cc: irenic.rajneesh, david.e.box, hdegoede, platform-driver-x86, LKML, linux-pm Hi Ilpo, Thanks for reviewing the patch. My response is inline. On 12/23/2025 4:29 AM, Ilpo Järvinen wrote: > On Tue, 16 Dec 2025, Xi Pardee wrote: > >> Change the datatypes pf num_lpm_modes and lpm_en_modes[] from int >> to u8. The u8 type is more appropriate and improves the readability >> and maintainability of the code. >> >> Signed-off-by: Xi Pardee <xi.pardee@linux.intel.com> >> --- >> drivers/platform/x86/intel/pmc/core.c | 18 ++++++++++-------- >> drivers/platform/x86/intel/pmc/core.h | 4 ++-- >> 2 files changed, 12 insertions(+), 10 deletions(-) >> >> diff --git a/drivers/platform/x86/intel/pmc/core.c b/drivers/platform/x86/intel/pmc/core.c >> index 7d7ae8a40b0ec..3e916228e7ed2 100644 >> --- a/drivers/platform/x86/intel/pmc/core.c >> +++ b/drivers/platform/x86/intel/pmc/core.c >> @@ -779,7 +779,7 @@ static int pmc_core_substate_res_show(struct seq_file *s, void *unused) >> struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; >> const int lpm_adj_x2 = pmc->map->lpm_res_counter_step_x2; >> u32 offset = pmc->map->lpm_residency_offset; >> - int mode; >> + u8 mode; >> >> seq_printf(s, "%-10s %-15s\n", "Substate", "Residency"); >> >> @@ -838,7 +838,7 @@ static void pmc_core_substate_req_header_show(struct seq_file *s, int pmc_index, >> enum header_type type) >> { >> struct pmc_dev *pmcdev = s->private; >> - int mode; >> + u8 mode; >> >> seq_printf(s, "%40s |", "Element"); >> pmc_for_each_mode(mode, pmcdev) >> @@ -880,7 +880,7 @@ static int pmc_core_substate_blk_req_show(struct seq_file *s, void *unused) >> const struct pmc_bit_map *map; >> >> for (map = maps[r_idx]; map->name; map++) { >> - int mode; >> + u8 mode; >> >> if (!map->blk) >> continue; >> @@ -953,7 +953,8 @@ static int pmc_core_substate_req_regs_show(struct seq_file *s, void *unused) >> u32 lpm_status; >> u32 lpm_status_live; >> const struct pmc_bit_map *map; >> - int mode, i, len = 32; >> + int i, len = 32; >> + u8 mode; >> >> /* >> * Capture the requirements and create a mask so that we only >> @@ -1065,7 +1066,7 @@ static int pmc_core_lpm_latch_mode_show(struct seq_file *s, void *unused) >> struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; >> bool c10; >> u32 reg; >> - int mode; >> + u8 mode; >> >> reg = pmc_core_reg_read(pmc, pmc->map->lpm_sts_latch_en_offset); >> if (reg & LPM_STS_LATCH_MODE) { >> @@ -1097,8 +1098,9 @@ static ssize_t pmc_core_lpm_latch_mode_write(struct file *file, >> struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; >> bool clear = false, c10 = false; >> unsigned char buf[8]; >> - int m, mode; >> + int mode; >> u32 reg; >> + u8 m; >> >> if (count > sizeof(buf) - 1) >> return -EINVAL; >> @@ -1490,8 +1492,8 @@ int pmc_core_pmt_get_lpm_req(struct pmc_dev *pmcdev, struct pmc *pmc, struct tel >> { >> const u8 *lpm_indices; >> int num_maps, mode_offset = 0; >> - int ret, mode; >> - int lpm_size; >> + int ret, lpm_size; >> + u8 mode; >> >> lpm_indices = pmc->map->lpm_reg_index; >> num_maps = pmc->map->lpm_num_maps; > Why is "mode" in pmc_core_get_low_power_modes() left untouched? > > (Unrelated to the patch, it seems to contain a double empty line as well.) I missed this function. Will change the type of "mode" in pmc_core_get_low_power_modes() in next version. Will add another patch to remove one empty line in next version. Thanks! Xi > >> diff --git a/drivers/platform/x86/intel/pmc/core.h b/drivers/platform/x86/intel/pmc/core.h >> index 272fb4f57f346..ead2f33ed3ed5 100644 >> --- a/drivers/platform/x86/intel/pmc/core.h >> +++ b/drivers/platform/x86/intel/pmc/core.h >> @@ -462,8 +462,8 @@ struct pmc_dev { >> struct mutex lock; /* generic mutex lock for PMC Core */ >> >> u64 s0ix_counter; >> - int num_lpm_modes; >> - int lpm_en_modes[LPM_MAX_NUM_MODES]; >> + u8 num_lpm_modes; >> + u8 lpm_en_modes[LPM_MAX_NUM_MODES]; >> void (*suspend)(struct pmc_dev *pmcdev); >> int (*resume)(struct pmc_dev *pmcdev); >> >> ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 2/3] platform/x86/intel/pmc: Move LPM mode attributes to PMC 2025-12-17 0:23 [PATCH 0/3] Enable substate residencies for multiple PMCs Xi Pardee 2025-12-17 0:23 ` [PATCH 1/3] platform/x86/intel/pmc: Change LPM mode fields to u8 Xi Pardee @ 2025-12-17 0:23 ` Xi Pardee 2025-12-23 12:34 ` Ilpo Järvinen 2025-12-17 0:23 ` [PATCH 3/3] platform/x86/intel/pmc: Enable substate residencies for multiple PMCs Xi Pardee 2 siblings, 1 reply; 8+ messages in thread From: Xi Pardee @ 2025-12-17 0:23 UTC (permalink / raw) To: xi.pardee, irenic.rajneesh, david.e.box, hdegoede, ilpo.jarvinen, platform-driver-x86, linux-kernel, linux-pm Move LPM modes attributes from the pmc_dev to the pmc structure. LPM modes are PMC-specific and should be stored within the pmc structure. After the change, LPM mode information will be retrieved and stored per PMC. The substate_requirements attribute in debugfs will display the requirements for each enabled LPM substate. Signed-off-by: Xi Pardee <xi.pardee@linux.intel.com> --- drivers/platform/x86/intel/pmc/core.c | 39 ++++++++++++++++++--------- drivers/platform/x86/intel/pmc/core.h | 15 +++++------ 2 files changed, 34 insertions(+), 20 deletions(-) diff --git a/drivers/platform/x86/intel/pmc/core.c b/drivers/platform/x86/intel/pmc/core.c index 3e916228e7ed2..25f77a9dc42c5 100644 --- a/drivers/platform/x86/intel/pmc/core.c +++ b/drivers/platform/x86/intel/pmc/core.c @@ -783,7 +783,7 @@ static int pmc_core_substate_res_show(struct seq_file *s, void *unused) seq_printf(s, "%-10s %-15s\n", "Substate", "Residency"); - pmc_for_each_mode(mode, pmcdev) { + pmc_for_each_mode(mode, pmc) { seq_printf(s, "%-10s %-15llu\n", pmc_lpm_modes[mode], adjust_lpm_residency(pmc, offset + (4 * mode), lpm_adj_x2)); } @@ -838,10 +838,11 @@ static void pmc_core_substate_req_header_show(struct seq_file *s, int pmc_index, enum header_type type) { struct pmc_dev *pmcdev = s->private; + struct pmc *pmc = pmcdev->pmcs[pmc_index]; u8 mode; seq_printf(s, "%40s |", "Element"); - pmc_for_each_mode(mode, pmcdev) + pmc_for_each_mode(mode, pmc) seq_printf(s, " %9s |", pmc_lpm_modes[mode]); if (type == HEADER_STATUS) { @@ -887,7 +888,7 @@ static int pmc_core_substate_blk_req_show(struct seq_file *s, void *unused) counter = pmc_core_reg_read(pmc, offset); seq_printf(s, "pmc%u: %34s |", pmc_idx, map->name); - pmc_for_each_mode(mode, pmcdev) { + pmc_for_each_mode(mode, pmc) { bool required = *lpm_req_regs & BIT(mode); seq_printf(s, " %9s |", required ? "Required" : " "); @@ -961,7 +962,7 @@ static int pmc_core_substate_req_regs_show(struct seq_file *s, void *unused) * show an element if it's required for at least one of the * enabled low power modes */ - pmc_for_each_mode(mode, pmcdev) + pmc_for_each_mode(mode, pmc) req_mask |= lpm_req_regs[mp + (mode * num_maps)]; /* Get the last latched status for this map */ @@ -987,7 +988,7 @@ static int pmc_core_substate_req_regs_show(struct seq_file *s, void *unused) seq_printf(s, "pmc%d: %34s |", pmc_idx, map[i].name); /* Loop over the enabled states and display if required */ - pmc_for_each_mode(mode, pmcdev) { + pmc_for_each_mode(mode, pmc) { bool required = lpm_req_regs[mp + (mode * num_maps)] & bit_mask; seq_printf(s, " %9s |", required ? "Required" : " "); @@ -1077,7 +1078,7 @@ static int pmc_core_lpm_latch_mode_show(struct seq_file *s, void *unused) c10 = true; } - pmc_for_each_mode(mode, pmcdev) { + pmc_for_each_mode(mode, pmc) { if ((BIT(mode) & reg) && !c10) seq_printf(s, " [%s]", pmc_lpm_modes[mode]); else @@ -1117,7 +1118,7 @@ static ssize_t pmc_core_lpm_latch_mode_write(struct file *file, mode = sysfs_match_string(pmc_lpm_modes, buf); /* Check string matches enabled mode */ - pmc_for_each_mode(m, pmcdev) + pmc_for_each_mode(m, pmc) if (mode == m) break; @@ -1213,9 +1214,8 @@ static bool pmc_core_pri_verify(u32 lpm_pri, u8 *mode_order) return true; } -void pmc_core_get_low_power_modes(struct pmc_dev *pmcdev) +static void pmc_core_pmc_get_low_power_modes(struct pmc_dev *pmcdev, struct pmc *pmc) { - struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; u8 pri_order[LPM_MAX_NUM_MODES] = LPM_DEFAULT_PRI; u8 mode_order[LPM_MAX_NUM_MODES]; u32 lpm_pri; @@ -1232,7 +1232,7 @@ void pmc_core_get_low_power_modes(struct pmc_dev *pmcdev) * Lower byte is enough to cover the number of lpm modes for all * platforms and hence mask the upper 3 bytes. */ - pmcdev->num_lpm_modes = hweight32(lpm_en & 0xFF); + pmc->num_lpm_modes = hweight32(lpm_en & 0xFF); /* Read 32 bit LPM_PRI register */ lpm_pri = pmc_core_reg_read(pmc, pmc->map->lpm_priority_offset); @@ -1261,7 +1261,22 @@ void pmc_core_get_low_power_modes(struct pmc_dev *pmcdev) if (!(BIT(mode) & lpm_en)) continue; - pmcdev->lpm_en_modes[i++] = mode; + pmc->lpm_en_modes[i++] = mode; + } +} + +static void pmc_core_get_low_power_modes(struct pmc_dev *pmcdev) +{ + unsigned int pmc_idx; + + for (pmc_idx = 0; pmc_idx < ARRAY_SIZE(pmcdev->pmcs); ++pmc_idx) { + struct pmc *pmc; + + pmc = pmcdev->pmcs[pmc_idx]; + if (!pmc) + continue; + + pmc_core_pmc_get_low_power_modes(pmcdev, pmc); } } @@ -1506,7 +1521,7 @@ int pmc_core_pmt_get_lpm_req(struct pmc_dev *pmcdev, struct pmc *pmc, struct tel return -ENOMEM; mode_offset = LPM_HEADER_OFFSET + LPM_MODE_OFFSET; - pmc_for_each_mode(mode, pmcdev) { + pmc_for_each_mode(mode, pmc) { u32 *req_offset = pmc->lpm_req_regs + (mode * num_maps); int m; diff --git a/drivers/platform/x86/intel/pmc/core.h b/drivers/platform/x86/intel/pmc/core.h index ead2f33ed3ed5..118c8740ad3aa 100644 --- a/drivers/platform/x86/intel/pmc/core.h +++ b/drivers/platform/x86/intel/pmc/core.h @@ -423,6 +423,8 @@ struct pmc_info { * specific attributes * @lpm_req_regs: List of substate requirements * @ltr_ign: Holds LTR ignore data while suspended + * @num_lpm_modes: Count of enabled modes + * @lpm_en_modes: Array of enabled modes from lowest to highest priority * * pmc contains info about one power management controller device. */ @@ -432,6 +434,8 @@ struct pmc { const struct pmc_reg_map *map; u32 *lpm_req_regs; u32 ltr_ign; + u8 num_lpm_modes; + u8 lpm_en_modes[LPM_MAX_NUM_MODES]; }; /** @@ -446,8 +450,6 @@ struct pmc { * @pkgc_res_cnt: Array of PKGC residency counters * @num_of_pkgc: Number of PKGC * @s0ix_counter: S0ix residency (step adjusted) - * @num_lpm_modes: Count of enabled modes - * @lpm_en_modes: Array of enabled modes from lowest to highest priority * @suspend: Function to perform platform specific suspend * @resume: Function to perform platform specific resume * @@ -462,8 +464,6 @@ struct pmc_dev { struct mutex lock; /* generic mutex lock for PMC Core */ u64 s0ix_counter; - u8 num_lpm_modes; - u8 lpm_en_modes[LPM_MAX_NUM_MODES]; void (*suspend)(struct pmc_dev *pmcdev); int (*resume)(struct pmc_dev *pmcdev); @@ -535,7 +535,6 @@ int pmc_core_send_ltr_ignore(struct pmc_dev *pmcdev, u32 value, int ignore); int pmc_core_resume_common(struct pmc_dev *pmcdev); int get_primary_reg_base(struct pmc *pmc); -void pmc_core_get_low_power_modes(struct pmc_dev *pmcdev); void pmc_core_punit_pmt_init(struct pmc_dev *pmcdev, u32 *guids); void pmc_core_set_device_d3(unsigned int device); @@ -563,10 +562,10 @@ int pmc_core_pmt_get_blk_sub_req(struct pmc_dev *pmcdev, struct pmc *pmc, extern const struct file_operations pmc_core_substate_req_regs_fops; extern const struct file_operations pmc_core_substate_blk_req_fops; -#define pmc_for_each_mode(mode, pmcdev) \ +#define pmc_for_each_mode(mode, pmc) \ for (unsigned int __i = 0, __cond; \ - __cond = __i < (pmcdev)->num_lpm_modes, \ - __cond && ((mode) = (pmcdev)->lpm_en_modes[__i]), \ + __cond = __i < (pmc)->num_lpm_modes, \ + __cond && ((mode) = (pmc)->lpm_en_modes[__i]), \ __cond; \ __i++) -- 2.43.0 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 2/3] platform/x86/intel/pmc: Move LPM mode attributes to PMC 2025-12-17 0:23 ` [PATCH 2/3] platform/x86/intel/pmc: Move LPM mode attributes to PMC Xi Pardee @ 2025-12-23 12:34 ` Ilpo Järvinen 2026-01-07 0:07 ` Xi Pardee 0 siblings, 1 reply; 8+ messages in thread From: Ilpo Järvinen @ 2025-12-23 12:34 UTC (permalink / raw) To: Xi Pardee Cc: irenic.rajneesh, david.e.box, hdegoede, platform-driver-x86, LKML, linux-pm On Tue, 16 Dec 2025, Xi Pardee wrote: > Move LPM modes attributes from the pmc_dev to the pmc > structure. LPM modes are PMC-specific and should be > stored within the pmc structure. This looks very short. Please reflow your commit message paragraphs to 72 chars. > After the change, LPM mode information will be retrieved > and stored per PMC. The substate_requirements attribute > in debugfs will display the requirements for each enabled > LPM substate. > > Signed-off-by: Xi Pardee <xi.pardee@linux.intel.com> > --- > drivers/platform/x86/intel/pmc/core.c | 39 ++++++++++++++++++--------- > drivers/platform/x86/intel/pmc/core.h | 15 +++++------ > 2 files changed, 34 insertions(+), 20 deletions(-) > > diff --git a/drivers/platform/x86/intel/pmc/core.c b/drivers/platform/x86/intel/pmc/core.c > index 3e916228e7ed2..25f77a9dc42c5 100644 > --- a/drivers/platform/x86/intel/pmc/core.c > +++ b/drivers/platform/x86/intel/pmc/core.c > @@ -783,7 +783,7 @@ static int pmc_core_substate_res_show(struct seq_file *s, void *unused) > > seq_printf(s, "%-10s %-15s\n", "Substate", "Residency"); > > - pmc_for_each_mode(mode, pmcdev) { > + pmc_for_each_mode(mode, pmc) { > seq_printf(s, "%-10s %-15llu\n", pmc_lpm_modes[mode], > adjust_lpm_residency(pmc, offset + (4 * mode), lpm_adj_x2)); > } > @@ -838,10 +838,11 @@ static void pmc_core_substate_req_header_show(struct seq_file *s, int pmc_index, > enum header_type type) > { > struct pmc_dev *pmcdev = s->private; > + struct pmc *pmc = pmcdev->pmcs[pmc_index]; > u8 mode; > > seq_printf(s, "%40s |", "Element"); > - pmc_for_each_mode(mode, pmcdev) > + pmc_for_each_mode(mode, pmc) > seq_printf(s, " %9s |", pmc_lpm_modes[mode]); > > if (type == HEADER_STATUS) { > @@ -887,7 +888,7 @@ static int pmc_core_substate_blk_req_show(struct seq_file *s, void *unused) > > counter = pmc_core_reg_read(pmc, offset); > seq_printf(s, "pmc%u: %34s |", pmc_idx, map->name); > - pmc_for_each_mode(mode, pmcdev) { > + pmc_for_each_mode(mode, pmc) { > bool required = *lpm_req_regs & BIT(mode); > > seq_printf(s, " %9s |", required ? "Required" : " "); > @@ -961,7 +962,7 @@ static int pmc_core_substate_req_regs_show(struct seq_file *s, void *unused) > * show an element if it's required for at least one of the > * enabled low power modes > */ > - pmc_for_each_mode(mode, pmcdev) > + pmc_for_each_mode(mode, pmc) > req_mask |= lpm_req_regs[mp + (mode * num_maps)]; > > /* Get the last latched status for this map */ > @@ -987,7 +988,7 @@ static int pmc_core_substate_req_regs_show(struct seq_file *s, void *unused) > seq_printf(s, "pmc%d: %34s |", pmc_idx, map[i].name); > > /* Loop over the enabled states and display if required */ > - pmc_for_each_mode(mode, pmcdev) { > + pmc_for_each_mode(mode, pmc) { > bool required = lpm_req_regs[mp + (mode * num_maps)] & > bit_mask; > seq_printf(s, " %9s |", required ? "Required" : " "); > @@ -1077,7 +1078,7 @@ static int pmc_core_lpm_latch_mode_show(struct seq_file *s, void *unused) > c10 = true; > } > > - pmc_for_each_mode(mode, pmcdev) { > + pmc_for_each_mode(mode, pmc) { > if ((BIT(mode) & reg) && !c10) > seq_printf(s, " [%s]", pmc_lpm_modes[mode]); > else > @@ -1117,7 +1118,7 @@ static ssize_t pmc_core_lpm_latch_mode_write(struct file *file, > mode = sysfs_match_string(pmc_lpm_modes, buf); > > /* Check string matches enabled mode */ > - pmc_for_each_mode(m, pmcdev) > + pmc_for_each_mode(m, pmc) > if (mode == m) > break; > > @@ -1213,9 +1214,8 @@ static bool pmc_core_pri_verify(u32 lpm_pri, u8 *mode_order) > return true; > } > > -void pmc_core_get_low_power_modes(struct pmc_dev *pmcdev) > +static void pmc_core_pmc_get_low_power_modes(struct pmc_dev *pmcdev, struct pmc *pmc) > { > - struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; > u8 pri_order[LPM_MAX_NUM_MODES] = LPM_DEFAULT_PRI; > u8 mode_order[LPM_MAX_NUM_MODES]; > u32 lpm_pri; > @@ -1232,7 +1232,7 @@ void pmc_core_get_low_power_modes(struct pmc_dev *pmcdev) > * Lower byte is enough to cover the number of lpm modes for all > * platforms and hence mask the upper 3 bytes. > */ > - pmcdev->num_lpm_modes = hweight32(lpm_en & 0xFF); > + pmc->num_lpm_modes = hweight32(lpm_en & 0xFF); > > /* Read 32 bit LPM_PRI register */ > lpm_pri = pmc_core_reg_read(pmc, pmc->map->lpm_priority_offset); > @@ -1261,7 +1261,22 @@ void pmc_core_get_low_power_modes(struct pmc_dev *pmcdev) > if (!(BIT(mode) & lpm_en)) > continue; > > - pmcdev->lpm_en_modes[i++] = mode; > + pmc->lpm_en_modes[i++] = mode; > + } > +} > + > +static void pmc_core_get_low_power_modes(struct pmc_dev *pmcdev) > +{ > + unsigned int pmc_idx; > + > + for (pmc_idx = 0; pmc_idx < ARRAY_SIZE(pmcdev->pmcs); ++pmc_idx) { Please always use post-increment when you are free to choose which one to use. > + struct pmc *pmc; > + > + pmc = pmcdev->pmcs[pmc_idx]; > + if (!pmc) > + continue; > + > + pmc_core_pmc_get_low_power_modes(pmcdev, pmc); > } > } > > @@ -1506,7 +1521,7 @@ int pmc_core_pmt_get_lpm_req(struct pmc_dev *pmcdev, struct pmc *pmc, struct tel > return -ENOMEM; > > mode_offset = LPM_HEADER_OFFSET + LPM_MODE_OFFSET; > - pmc_for_each_mode(mode, pmcdev) { > + pmc_for_each_mode(mode, pmc) { > u32 *req_offset = pmc->lpm_req_regs + (mode * num_maps); > int m; > > diff --git a/drivers/platform/x86/intel/pmc/core.h b/drivers/platform/x86/intel/pmc/core.h > index ead2f33ed3ed5..118c8740ad3aa 100644 > --- a/drivers/platform/x86/intel/pmc/core.h > +++ b/drivers/platform/x86/intel/pmc/core.h > @@ -423,6 +423,8 @@ struct pmc_info { > * specific attributes > * @lpm_req_regs: List of substate requirements > * @ltr_ign: Holds LTR ignore data while suspended > + * @num_lpm_modes: Count of enabled modes > + * @lpm_en_modes: Array of enabled modes from lowest to highest priority > * > * pmc contains info about one power management controller device. > */ > @@ -432,6 +434,8 @@ struct pmc { > const struct pmc_reg_map *map; > u32 *lpm_req_regs; > u32 ltr_ign; > + u8 num_lpm_modes; > + u8 lpm_en_modes[LPM_MAX_NUM_MODES]; > }; > > /** > @@ -446,8 +450,6 @@ struct pmc { > * @pkgc_res_cnt: Array of PKGC residency counters > * @num_of_pkgc: Number of PKGC > * @s0ix_counter: S0ix residency (step adjusted) > - * @num_lpm_modes: Count of enabled modes > - * @lpm_en_modes: Array of enabled modes from lowest to highest priority > * @suspend: Function to perform platform specific suspend > * @resume: Function to perform platform specific resume > * > @@ -462,8 +464,6 @@ struct pmc_dev { > struct mutex lock; /* generic mutex lock for PMC Core */ > > u64 s0ix_counter; > - u8 num_lpm_modes; > - u8 lpm_en_modes[LPM_MAX_NUM_MODES]; > void (*suspend)(struct pmc_dev *pmcdev); > int (*resume)(struct pmc_dev *pmcdev); > > @@ -535,7 +535,6 @@ int pmc_core_send_ltr_ignore(struct pmc_dev *pmcdev, u32 value, int ignore); > > int pmc_core_resume_common(struct pmc_dev *pmcdev); > int get_primary_reg_base(struct pmc *pmc); > -void pmc_core_get_low_power_modes(struct pmc_dev *pmcdev); > void pmc_core_punit_pmt_init(struct pmc_dev *pmcdev, u32 *guids); > void pmc_core_set_device_d3(unsigned int device); > > @@ -563,10 +562,10 @@ int pmc_core_pmt_get_blk_sub_req(struct pmc_dev *pmcdev, struct pmc *pmc, > extern const struct file_operations pmc_core_substate_req_regs_fops; > extern const struct file_operations pmc_core_substate_blk_req_fops; > > -#define pmc_for_each_mode(mode, pmcdev) \ > +#define pmc_for_each_mode(mode, pmc) \ > for (unsigned int __i = 0, __cond; \ > - __cond = __i < (pmcdev)->num_lpm_modes, \ > - __cond && ((mode) = (pmcdev)->lpm_en_modes[__i]), \ > + __cond = __i < (pmc)->num_lpm_modes, \ > + __cond && ((mode) = (pmc)->lpm_en_modes[__i]), \ > __cond; \ > __i++) > > -- i. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2/3] platform/x86/intel/pmc: Move LPM mode attributes to PMC 2025-12-23 12:34 ` Ilpo Järvinen @ 2026-01-07 0:07 ` Xi Pardee 0 siblings, 0 replies; 8+ messages in thread From: Xi Pardee @ 2026-01-07 0:07 UTC (permalink / raw) To: Ilpo Järvinen Cc: irenic.rajneesh, david.e.box, hdegoede, platform-driver-x86, LKML, linux-pm Hi Ilpo, Thanks for the review. My response is inline. On 12/23/2025 4:34 AM, Ilpo Järvinen wrote: > On Tue, 16 Dec 2025, Xi Pardee wrote: > >> Move LPM modes attributes from the pmc_dev to the pmc >> structure. LPM modes are PMC-specific and should be >> stored within the pmc structure. > This looks very short. Please reflow your commit message paragraphs to 72 > chars. I will rearrange the commit message in next version. > >> After the change, LPM mode information will be retrieved >> and stored per PMC. The substate_requirements attribute >> in debugfs will display the requirements for each enabled >> LPM substate. >> >> Signed-off-by: Xi Pardee <xi.pardee@linux.intel.com> >> --- >> drivers/platform/x86/intel/pmc/core.c | 39 ++++++++++++++++++--------- >> drivers/platform/x86/intel/pmc/core.h | 15 +++++------ >> 2 files changed, 34 insertions(+), 20 deletions(-) >> >> diff --git a/drivers/platform/x86/intel/pmc/core.c b/drivers/platform/x86/intel/pmc/core.c >> index 3e916228e7ed2..25f77a9dc42c5 100644 >> --- a/drivers/platform/x86/intel/pmc/core.c >> +++ b/drivers/platform/x86/intel/pmc/core.c >> @@ -783,7 +783,7 @@ static int pmc_core_substate_res_show(struct seq_file *s, void *unused) >> >> seq_printf(s, "%-10s %-15s\n", "Substate", "Residency"); >> >> - pmc_for_each_mode(mode, pmcdev) { >> + pmc_for_each_mode(mode, pmc) { >> seq_printf(s, "%-10s %-15llu\n", pmc_lpm_modes[mode], >> adjust_lpm_residency(pmc, offset + (4 * mode), lpm_adj_x2)); >> } >> @@ -838,10 +838,11 @@ static void pmc_core_substate_req_header_show(struct seq_file *s, int pmc_index, >> enum header_type type) >> { >> struct pmc_dev *pmcdev = s->private; >> + struct pmc *pmc = pmcdev->pmcs[pmc_index]; >> u8 mode; >> >> seq_printf(s, "%40s |", "Element"); >> - pmc_for_each_mode(mode, pmcdev) >> + pmc_for_each_mode(mode, pmc) >> seq_printf(s, " %9s |", pmc_lpm_modes[mode]); >> >> if (type == HEADER_STATUS) { >> @@ -887,7 +888,7 @@ static int pmc_core_substate_blk_req_show(struct seq_file *s, void *unused) >> >> counter = pmc_core_reg_read(pmc, offset); >> seq_printf(s, "pmc%u: %34s |", pmc_idx, map->name); >> - pmc_for_each_mode(mode, pmcdev) { >> + pmc_for_each_mode(mode, pmc) { >> bool required = *lpm_req_regs & BIT(mode); >> >> seq_printf(s, " %9s |", required ? "Required" : " "); >> @@ -961,7 +962,7 @@ static int pmc_core_substate_req_regs_show(struct seq_file *s, void *unused) >> * show an element if it's required for at least one of the >> * enabled low power modes >> */ >> - pmc_for_each_mode(mode, pmcdev) >> + pmc_for_each_mode(mode, pmc) >> req_mask |= lpm_req_regs[mp + (mode * num_maps)]; >> >> /* Get the last latched status for this map */ >> @@ -987,7 +988,7 @@ static int pmc_core_substate_req_regs_show(struct seq_file *s, void *unused) >> seq_printf(s, "pmc%d: %34s |", pmc_idx, map[i].name); >> >> /* Loop over the enabled states and display if required */ >> - pmc_for_each_mode(mode, pmcdev) { >> + pmc_for_each_mode(mode, pmc) { >> bool required = lpm_req_regs[mp + (mode * num_maps)] & >> bit_mask; >> seq_printf(s, " %9s |", required ? "Required" : " "); >> @@ -1077,7 +1078,7 @@ static int pmc_core_lpm_latch_mode_show(struct seq_file *s, void *unused) >> c10 = true; >> } >> >> - pmc_for_each_mode(mode, pmcdev) { >> + pmc_for_each_mode(mode, pmc) { >> if ((BIT(mode) & reg) && !c10) >> seq_printf(s, " [%s]", pmc_lpm_modes[mode]); >> else >> @@ -1117,7 +1118,7 @@ static ssize_t pmc_core_lpm_latch_mode_write(struct file *file, >> mode = sysfs_match_string(pmc_lpm_modes, buf); >> >> /* Check string matches enabled mode */ >> - pmc_for_each_mode(m, pmcdev) >> + pmc_for_each_mode(m, pmc) >> if (mode == m) >> break; >> >> @@ -1213,9 +1214,8 @@ static bool pmc_core_pri_verify(u32 lpm_pri, u8 *mode_order) >> return true; >> } >> >> -void pmc_core_get_low_power_modes(struct pmc_dev *pmcdev) >> +static void pmc_core_pmc_get_low_power_modes(struct pmc_dev *pmcdev, struct pmc *pmc) >> { >> - struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; >> u8 pri_order[LPM_MAX_NUM_MODES] = LPM_DEFAULT_PRI; >> u8 mode_order[LPM_MAX_NUM_MODES]; >> u32 lpm_pri; >> @@ -1232,7 +1232,7 @@ void pmc_core_get_low_power_modes(struct pmc_dev *pmcdev) >> * Lower byte is enough to cover the number of lpm modes for all >> * platforms and hence mask the upper 3 bytes. >> */ >> - pmcdev->num_lpm_modes = hweight32(lpm_en & 0xFF); >> + pmc->num_lpm_modes = hweight32(lpm_en & 0xFF); >> >> /* Read 32 bit LPM_PRI register */ >> lpm_pri = pmc_core_reg_read(pmc, pmc->map->lpm_priority_offset); >> @@ -1261,7 +1261,22 @@ void pmc_core_get_low_power_modes(struct pmc_dev *pmcdev) >> if (!(BIT(mode) & lpm_en)) >> continue; >> >> - pmcdev->lpm_en_modes[i++] = mode; >> + pmc->lpm_en_modes[i++] = mode; >> + } >> +} >> + >> +static void pmc_core_get_low_power_modes(struct pmc_dev *pmcdev) >> +{ >> + unsigned int pmc_idx; >> + >> + for (pmc_idx = 0; pmc_idx < ARRAY_SIZE(pmcdev->pmcs); ++pmc_idx) { > Please always use post-increment when you are free to choose which one to > use. Will change to post-increment in next version. Thanks! Xi > >> + struct pmc *pmc; >> + >> + pmc = pmcdev->pmcs[pmc_idx]; >> + if (!pmc) >> + continue; >> + >> + pmc_core_pmc_get_low_power_modes(pmcdev, pmc); >> } >> } >> >> @@ -1506,7 +1521,7 @@ int pmc_core_pmt_get_lpm_req(struct pmc_dev *pmcdev, struct pmc *pmc, struct tel >> return -ENOMEM; >> >> mode_offset = LPM_HEADER_OFFSET + LPM_MODE_OFFSET; >> - pmc_for_each_mode(mode, pmcdev) { >> + pmc_for_each_mode(mode, pmc) { >> u32 *req_offset = pmc->lpm_req_regs + (mode * num_maps); >> int m; >> >> diff --git a/drivers/platform/x86/intel/pmc/core.h b/drivers/platform/x86/intel/pmc/core.h >> index ead2f33ed3ed5..118c8740ad3aa 100644 >> --- a/drivers/platform/x86/intel/pmc/core.h >> +++ b/drivers/platform/x86/intel/pmc/core.h >> @@ -423,6 +423,8 @@ struct pmc_info { >> * specific attributes >> * @lpm_req_regs: List of substate requirements >> * @ltr_ign: Holds LTR ignore data while suspended >> + * @num_lpm_modes: Count of enabled modes >> + * @lpm_en_modes: Array of enabled modes from lowest to highest priority >> * >> * pmc contains info about one power management controller device. >> */ >> @@ -432,6 +434,8 @@ struct pmc { >> const struct pmc_reg_map *map; >> u32 *lpm_req_regs; >> u32 ltr_ign; >> + u8 num_lpm_modes; >> + u8 lpm_en_modes[LPM_MAX_NUM_MODES]; >> }; >> >> /** >> @@ -446,8 +450,6 @@ struct pmc { >> * @pkgc_res_cnt: Array of PKGC residency counters >> * @num_of_pkgc: Number of PKGC >> * @s0ix_counter: S0ix residency (step adjusted) >> - * @num_lpm_modes: Count of enabled modes >> - * @lpm_en_modes: Array of enabled modes from lowest to highest priority >> * @suspend: Function to perform platform specific suspend >> * @resume: Function to perform platform specific resume >> * >> @@ -462,8 +464,6 @@ struct pmc_dev { >> struct mutex lock; /* generic mutex lock for PMC Core */ >> >> u64 s0ix_counter; >> - u8 num_lpm_modes; >> - u8 lpm_en_modes[LPM_MAX_NUM_MODES]; >> void (*suspend)(struct pmc_dev *pmcdev); >> int (*resume)(struct pmc_dev *pmcdev); >> >> @@ -535,7 +535,6 @@ int pmc_core_send_ltr_ignore(struct pmc_dev *pmcdev, u32 value, int ignore); >> >> int pmc_core_resume_common(struct pmc_dev *pmcdev); >> int get_primary_reg_base(struct pmc *pmc); >> -void pmc_core_get_low_power_modes(struct pmc_dev *pmcdev); >> void pmc_core_punit_pmt_init(struct pmc_dev *pmcdev, u32 *guids); >> void pmc_core_set_device_d3(unsigned int device); >> >> @@ -563,10 +562,10 @@ int pmc_core_pmt_get_blk_sub_req(struct pmc_dev *pmcdev, struct pmc *pmc, >> extern const struct file_operations pmc_core_substate_req_regs_fops; >> extern const struct file_operations pmc_core_substate_blk_req_fops; >> >> -#define pmc_for_each_mode(mode, pmcdev) \ >> +#define pmc_for_each_mode(mode, pmc) \ >> for (unsigned int __i = 0, __cond; \ >> - __cond = __i < (pmcdev)->num_lpm_modes, \ >> - __cond && ((mode) = (pmcdev)->lpm_en_modes[__i]), \ >> + __cond = __i < (pmc)->num_lpm_modes, \ >> + __cond && ((mode) = (pmc)->lpm_en_modes[__i]), \ >> __cond; \ >> __i++) >> >> ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 3/3] platform/x86/intel/pmc: Enable substate residencies for multiple PMCs 2025-12-17 0:23 [PATCH 0/3] Enable substate residencies for multiple PMCs Xi Pardee 2025-12-17 0:23 ` [PATCH 1/3] platform/x86/intel/pmc: Change LPM mode fields to u8 Xi Pardee 2025-12-17 0:23 ` [PATCH 2/3] platform/x86/intel/pmc: Move LPM mode attributes to PMC Xi Pardee @ 2025-12-17 0:23 ` Xi Pardee 2 siblings, 0 replies; 8+ messages in thread From: Xi Pardee @ 2025-12-17 0:23 UTC (permalink / raw) To: xi.pardee, irenic.rajneesh, david.e.box, hdegoede, ilpo.jarvinen, platform-driver-x86, linux-kernel, linux-pm Enable substate residencies support for multiple PMCs. Previously substate residencies were shown only for the primary PMC. This change enables substate residencies for all available PMCs. Signed-off-by: Xi Pardee <xi.pardee@linux.intel.com> --- drivers/platform/x86/intel/pmc/core.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/drivers/platform/x86/intel/pmc/core.c b/drivers/platform/x86/intel/pmc/core.c index 25f77a9dc42c5..1f84d5ef47458 100644 --- a/drivers/platform/x86/intel/pmc/core.c +++ b/drivers/platform/x86/intel/pmc/core.c @@ -776,16 +776,26 @@ static inline u64 adjust_lpm_residency(struct pmc *pmc, u32 offset, static int pmc_core_substate_res_show(struct seq_file *s, void *unused) { struct pmc_dev *pmcdev = s->private; - struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; - const int lpm_adj_x2 = pmc->map->lpm_res_counter_step_x2; - u32 offset = pmc->map->lpm_residency_offset; - u8 mode; + unsigned int pmc_idx; + + for (pmc_idx = 0; pmc_idx < ARRAY_SIZE(pmcdev->pmcs); ++pmc_idx) { + int lpm_adj_x2; + struct pmc *pmc; + u32 offset; + u8 mode; - seq_printf(s, "%-10s %-15s\n", "Substate", "Residency"); + pmc = pmcdev->pmcs[pmc_idx]; + if (!pmc) + continue; - pmc_for_each_mode(mode, pmc) { - seq_printf(s, "%-10s %-15llu\n", pmc_lpm_modes[mode], - adjust_lpm_residency(pmc, offset + (4 * mode), lpm_adj_x2)); + lpm_adj_x2 = pmc->map->lpm_res_counter_step_x2; + offset = pmc->map->lpm_residency_offset; + + seq_printf(s, "pmc%u %10s %15s\n", pmc_idx, "Substate", "Residency"); + pmc_for_each_mode(mode, pmc) { + seq_printf(s, "%15s %15llu\n", pmc_lpm_modes[mode], + adjust_lpm_residency(pmc, offset + (4 * mode), lpm_adj_x2)); + } } return 0; -- 2.43.0 ^ permalink raw reply related [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-01-07 0:08 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-12-17 0:23 [PATCH 0/3] Enable substate residencies for multiple PMCs Xi Pardee 2025-12-17 0:23 ` [PATCH 1/3] platform/x86/intel/pmc: Change LPM mode fields to u8 Xi Pardee 2025-12-23 12:29 ` Ilpo Järvinen 2026-01-06 23:45 ` Xi Pardee 2025-12-17 0:23 ` [PATCH 2/3] platform/x86/intel/pmc: Move LPM mode attributes to PMC Xi Pardee 2025-12-23 12:34 ` Ilpo Järvinen 2026-01-07 0:07 ` Xi Pardee 2025-12-17 0:23 ` [PATCH 3/3] platform/x86/intel/pmc: Enable substate residencies for multiple PMCs Xi Pardee
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.