platform/x86/intel/pmc: Enable PkgC LTR blocking counter

Enable the Package C-state LTR blocking counter in the PMT telemetry
region. This counter records how many times any Package C-state entry
is blocked for the specified reasons.

Add pmc_core_pkgc_counters_show() as a common helper to display
package C-state blocking counters from the telemetry region.

Signed-off-by: Xi Pardee <xi.pardee@linux.intel.com>
Link: https://patch.msgid.link/20260505043342.2573556-3-xi.pardee@linux.intel.com
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
This commit is contained in:
Xi Pardee 2026-05-04 21:33:33 -07:00 committed by Ilpo Järvinen
parent dfe614f82e
commit 38c79dd63b
No known key found for this signature in database
GPG Key ID: 59AC4F6153E5CE31
2 changed files with 82 additions and 12 deletions

View File

@ -1071,6 +1071,34 @@ static int pmc_core_die_c6_us_show(struct seq_file *s, void *unused)
}
DEFINE_SHOW_ATTRIBUTE(pmc_core_die_c6_us);
static int pmc_core_pkgc_counters_show(struct seq_file *s,
struct telem_endpoint *ep,
u32 offset, const char **counters)
{
unsigned int i;
u32 counter;
int ret;
for (i = 0; counters[i]; i++) {
ret = pmt_telem_read32(ep, offset + i, &counter, 1);
if (ret)
return ret;
seq_printf(s, "%-30s %-30u\n", counters[i], counter);
}
return 0;
}
static int pmc_core_pkgc_ltr_blocker_show(struct seq_file *s, void *unused)
{
struct pmc_dev *pmcdev = s->private;
return pmc_core_pkgc_counters_show(s, pmcdev->pc_ep,
pmcdev->pkgc_ltr_blocker_offset,
pmcdev->pkgc_ltr_blocker_counters);
}
DEFINE_SHOW_ATTRIBUTE(pmc_core_pkgc_ltr_blocker);
static int pmc_core_lpm_latch_mode_show(struct seq_file *s, void *unused)
{
struct pmc_dev *pmcdev = s->private;
@ -1322,7 +1350,7 @@ static struct telem_endpoint *pmc_core_register_endpoint(struct pci_dev *pcidev,
return ERR_PTR(-ENODEV);
}
void pmc_core_punit_pmt_init(struct pmc_dev *pmcdev, u32 *guids)
void pmc_core_punit_pmt_init(struct pmc_dev *pmcdev, struct pmc_dev_info *pmc_dev_info)
{
struct telem_endpoint *ep;
@ -1333,16 +1361,32 @@ void pmc_core_punit_pmt_init(struct pmc_dev *pmcdev, u32 *guids)
return;
}
ep = pmc_core_register_endpoint(pcidev, guids);
if (IS_ERR(ep)) {
dev_err(&pmcdev->pdev->dev,
"pmc_core: couldn't get DMU telem endpoint %ld",
PTR_ERR(ep));
return;
if (pmc_dev_info->dmu_guids) {
ep = pmc_core_register_endpoint(pcidev, pmc_dev_info->dmu_guids);
if (IS_ERR(ep)) {
dev_err(&pmcdev->pdev->dev,
"pmc_core: couldn't get DMU telem endpoint %ld",
PTR_ERR(ep));
return;
}
pmcdev->punit_ep = ep;
pmcdev->die_c6_offset = MTL_PMT_DMU_DIE_C6_OFFSET;
}
pmcdev->punit_ep = ep;
pmcdev->die_c6_offset = MTL_PMT_DMU_DIE_C6_OFFSET;
if (pmc_dev_info->pc_guid) {
ep = pmt_telem_find_and_register_endpoint(&pcidev->dev, pmc_dev_info->pc_guid, 0);
if (IS_ERR(ep)) {
dev_err(&pmcdev->pdev->dev,
"pmc_core: couldn't get Package C-state telem endpoint %ld",
PTR_ERR(ep));
return;
}
pmcdev->pc_ep = ep;
pmcdev->pkgc_ltr_blocker_counters = pmc_dev_info->pkgc_ltr_blocker_counters;
pmcdev->pkgc_ltr_blocker_offset = pmc_dev_info->pkgc_ltr_blocker_offset;
}
}
void pmc_core_set_device_d3(unsigned int device)
@ -1466,6 +1510,13 @@ static void pmc_core_dbgfs_register(struct pmc_dev *pmcdev, struct pmc_dev_info
pmcdev->dbgfs_dir, pmcdev,
&pmc_core_die_c6_us_fops);
}
if (pmcdev->pc_ep) {
debugfs_create_file("pkgc_ltr_blocker_show", 0444,
pmcdev->dbgfs_dir, pmcdev,
&pmc_core_pkgc_ltr_blocker_fops);
}
}
/*
@ -1716,8 +1767,8 @@ int generic_core_init(struct pmc_dev *pmcdev, struct pmc_dev_info *pmc_dev_info)
}
pmc_core_get_low_power_modes(pmcdev);
if (pmc_dev_info->dmu_guids)
pmc_core_punit_pmt_init(pmcdev, pmc_dev_info->dmu_guids);
if (pmc_dev_info->dmu_guids || pmc_dev_info->pc_guid)
pmc_core_punit_pmt_init(pmcdev, pmc_dev_info);
if (ssram) {
ret = pmc_core_get_telem_info(pmcdev, pmc_dev_info);
@ -1738,6 +1789,9 @@ int generic_core_init(struct pmc_dev *pmcdev, struct pmc_dev_info *pmc_dev_info)
if (pmcdev->punit_ep)
pmt_telem_unregister_endpoint(pmcdev->punit_ep);
if (pmcdev->pc_ep)
pmt_telem_unregister_endpoint(pmcdev->pc_ep);
return ret;
}
@ -1834,6 +1888,9 @@ static void pmc_core_clean_structure(struct platform_device *pdev)
if (pmcdev->punit_ep)
pmt_telem_unregister_endpoint(pmcdev->punit_ep);
if (pmcdev->pc_ep)
pmt_telem_unregister_endpoint(pmcdev->pc_ep);
platform_set_drvdata(pdev, NULL);
}

View File

@ -453,6 +453,9 @@ struct pmc {
* @suspend: Function to perform platform specific suspend
* @resume: Function to perform platform specific resume
*
* @pkgc_ltr_blocker_counters: Array of PKGC LTR blocker counters
* @pkgc_ltr_blocker_offset: Offset to PKGC LTR blockers in telemetry region
*
* pmc_dev contains info about power management controller device.
*/
struct pmc_dev {
@ -471,8 +474,12 @@ struct pmc_dev {
u8 num_of_pkgc;
u32 die_c6_offset;
struct telem_endpoint *pc_ep;
struct telem_endpoint *punit_ep;
struct pmc_info *regmap_list;
const char **pkgc_ltr_blocker_counters;
u32 pkgc_ltr_blocker_offset;
};
enum pmc_index {
@ -486,12 +493,15 @@ enum pmc_index {
* struct pmc_dev_info - Structure to keep PMC device info
* @pci_func: Function number of the primary PMC
* @dmu_guids: List of Die Management Unit GUID
* @pc_guid: GUID for telemetry region to read PKGC blocker info
* @pkgc_ltr_blocker_offset: Offset to PKGC LTR blockers in telemetry region
* @regmap_list: Pointer to a list of pmc_info structure that could be
* available for the platform. When set, this field implies
* SSRAM support.
* @map: Pointer to a pmc_reg_map struct that contains platform
* specific attributes of the primary PMC
* @sub_req_show: File operations to show substate requirements
* @pkgc_ltr_blocker_counters: Array of PKGC LTR blocker counters
* @suspend: Function to perform platform specific suspend
* @resume: Function to perform platform specific resume
* @init: Function to perform platform specific init action
@ -500,9 +510,12 @@ enum pmc_index {
struct pmc_dev_info {
u8 pci_func;
u32 *dmu_guids;
u32 pc_guid;
u32 pkgc_ltr_blocker_offset;
struct pmc_info *regmap_list;
const struct pmc_reg_map *map;
const struct file_operations *sub_req_show;
const char **pkgc_ltr_blocker_counters;
void (*suspend)(struct pmc_dev *pmcdev);
int (*resume)(struct pmc_dev *pmcdev);
int (*init)(struct pmc_dev *pmcdev, struct pmc_dev_info *pmc_dev_info);
@ -535,7 +548,7 @@ 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_punit_pmt_init(struct pmc_dev *pmcdev, u32 *guids);
void pmc_core_punit_pmt_init(struct pmc_dev *pmcdev, struct pmc_dev_info *pmc_dev_info);
void pmc_core_set_device_d3(unsigned int device);
int generic_core_init(struct pmc_dev *pmcdev, struct pmc_dev_info *pmc_dev_info);