public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH V2 00/17] Add ACPI-based PMT discovery support for Intel PMC
@ 2026-03-25  1:48 David E. Box
  2026-03-25  1:48 ` [PATCH V2 01/17] platform/x86/intel/pmt: Add pre/post decode hooks around header parsing David E. Box
                   ` (16 more replies)
  0 siblings, 17 replies; 27+ messages in thread
From: David E. Box @ 2026-03-25  1:48 UTC (permalink / raw)
  To: irenic.rajneesh, ilpo.jarvinen, srinivas.pandruvada, xi.pardee,
	david.e.box
  Cc: hansg, linux-kernel, platform-driver-x86

This series adds ACPI-based PMT discovery support and wires it into the
Intel PMC telemetry stack for Nova Lake S.

Today, PMT discovery flow is primarily PCI-oriented. Some platforms expose
PMT discovery via ACPI _DSD, and PMC telemetry needs to consume that path
for both standalone and companion-device cases. This series addresses that
in three logical steps:

    1. Prepare intel_vsec for ACPI-backed discovery
    2. Refactor PMT class handling so discovery source is
       abstracted (PCI or ACPI)
    3. Add/enable PMC consumers using ACPI discovery, including NVL
       SSRAM support

Patches for step 1 were previously accepted. V2 includes the remaining
integration patches plus a new patch addressing review feedback on
cleanup.h patterns in ssram_telemetry.c.

Series layout

    01-06: intel_vsec cleanup/generalization for ACPI-capable discovery
           plumbing. Previously posted and accepted.

    07-12: PMT class refactor and ACPI discovery-source support
           Major patches:
           Patch 12 - adds ACPI support in PMT driver

    13-17: PMC driver integration
           Major patches:
           Patch 15 - adds ACPI discovery support in ssram driver
           Patch 17 - adds NVL IDs for SSRAM discovery

           Notable changes in V2:
           Patch 14 - new commit fixing __free() cleanup patterns per Ilpo's review

David E. Box (15):
  platform/x86/intel/pmt: Add pre/post decode hooks around header
    parsing
  platform/x86/intel/pmt/crashlog: Split init into pre-decode
  platform/x86/intel/pmt/telemetry: Move overlap check to post-decode
    hook
  platform/x86/intel/pmt: Move header decode into common helper
  platform/x86/intel/pmt: Pass discovery index instead of resource
  platform/x86/intel/pmt: Unify header fetch and add ACPI source
  platform/x86/intel/pmc: Add PMC SSRAM Kconfig description
  platform/x86/intel/pmc: Add ACPI PWRM telemetry driver for Nova Lake S
  platform/x86/intel/pmc/ssram: Rename probe and PCI ID table for
    consistency
  platform/x86/intel/pmc/ssram: Refactor DEVID/PWRMBASE extraction into
    helper
  platform/x86/intel/pmc/ssram: Add PCI platform data
  platform/x86/intel/pmc/ssram_telemetry: Fix cleanup pattern for
    __free() variables
  platform/x86/intel/pmc/ssram: Add ACPI discovery scaffolding
  platform/x86/intel/pmc/ssram: Make PMT registration optional
  platform/x86/intel/pmc: Add NVL PCI IDs for SSRAM telemetry discovery

Xi Pardee (2):
  platform/x86/intel/pmc/ssram: Use fixed-size static pmc array
  platform/x86/intel/pmc/ssram: Refactor memory barrier for reentrant
    probe

 drivers/platform/x86/intel/pmc/Kconfig        |  25 ++
 drivers/platform/x86/intel/pmc/Makefile       |   2 +
 drivers/platform/x86/intel/pmc/core.h         |  20 ++
 .../platform/x86/intel/pmc/pwrm_telemetry.c   | 214 ++++++++++++++
 .../platform/x86/intel/pmc/ssram_telemetry.c  | 267 +++++++++++++-----
 drivers/platform/x86/intel/pmt/class.c        | 160 ++++++++++-
 drivers/platform/x86/intel/pmt/class.h        |  20 +-
 drivers/platform/x86/intel/pmt/crashlog.c     |  22 +-
 drivers/platform/x86/intel/pmt/telemetry.c    |  32 +--
 9 files changed, 636 insertions(+), 126 deletions(-)
 create mode 100644 drivers/platform/x86/intel/pmc/pwrm_telemetry.c


base-commit: a5877e921389178f994a5ec15a145d7e7ba3ec65
--
2.43.0


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

* [PATCH V2 01/17] platform/x86/intel/pmt: Add pre/post decode hooks around header parsing
  2026-03-25  1:48 [PATCH V2 00/17] Add ACPI-based PMT discovery support for Intel PMC David E. Box
@ 2026-03-25  1:48 ` David E. Box
  2026-03-25  1:48 ` [PATCH V2 02/17] platform/x86/intel/pmt/crashlog: Split init into pre-decode David E. Box
                   ` (15 subsequent siblings)
  16 siblings, 0 replies; 27+ messages in thread
From: David E. Box @ 2026-03-25  1:48 UTC (permalink / raw)
  To: irenic.rajneesh, ilpo.jarvinen, srinivas.pandruvada, xi.pardee,
	david.e.box
  Cc: hansg, linux-kernel, platform-driver-x86

Add optional pre- and post-decode callbacks to the PMT class so namespaces
can perform setup and cleanup steps around header parsing.

  - Add pmt_pre_decode() and pmt_post_decode() to struct
    intel_pmt_namespace.
  - Update intel_pmt_dev_create() to invoke, in order:
      pre → header_decode() → post.
  - Keep the existing pmt_header_decode() callback unchanged.

No functional changes. This adds flexibility for upcoming decoders while
preserving current behavior.

Signed-off-by: David E. Box <david.e.box@linux.intel.com>
---

V2 - No changes

 drivers/platform/x86/intel/pmt/class.c | 12 ++++++++++++
 drivers/platform/x86/intel/pmt/class.h |  4 ++++
 2 files changed, 16 insertions(+)

diff --git a/drivers/platform/x86/intel/pmt/class.c b/drivers/platform/x86/intel/pmt/class.c
index b4c9964df807..9b315334a69b 100644
--- a/drivers/platform/x86/intel/pmt/class.c
+++ b/drivers/platform/x86/intel/pmt/class.c
@@ -381,10 +381,22 @@ int intel_pmt_dev_create(struct intel_pmt_entry *entry, struct intel_pmt_namespa
 	if (IS_ERR(entry->disc_table))
 		return PTR_ERR(entry->disc_table);
 
+	if (ns->pmt_pre_decode) {
+		ret = ns->pmt_pre_decode(intel_vsec_dev, entry);
+		if (ret)
+			return ret;
+	}
+
 	ret = ns->pmt_header_decode(entry, dev);
 	if (ret)
 		return ret;
 
+	if (ns->pmt_post_decode) {
+		ret = ns->pmt_post_decode(intel_vsec_dev, entry);
+		if (ret)
+			return ret;
+	}
+
 	ret = intel_pmt_populate_entry(entry, intel_vsec_dev, disc_res);
 	if (ret)
 		return ret;
diff --git a/drivers/platform/x86/intel/pmt/class.h b/drivers/platform/x86/intel/pmt/class.h
index 1ae56a5baad2..ff39014b208c 100644
--- a/drivers/platform/x86/intel/pmt/class.h
+++ b/drivers/platform/x86/intel/pmt/class.h
@@ -62,6 +62,10 @@ struct intel_pmt_namespace {
 	struct xarray *xa;
 	int (*pmt_header_decode)(struct intel_pmt_entry *entry,
 				 struct device *dev);
+	int (*pmt_pre_decode)(struct intel_vsec_device *ivdev,
+			      struct intel_pmt_entry *entry);
+	int (*pmt_post_decode)(struct intel_vsec_device *ivdev,
+			       struct intel_pmt_entry *entry);
 	int (*pmt_add_endpoint)(struct intel_vsec_device *ivdev,
 				struct intel_pmt_entry *entry);
 };
-- 
2.43.0


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

* [PATCH V2 02/17] platform/x86/intel/pmt/crashlog: Split init into pre-decode
  2026-03-25  1:48 [PATCH V2 00/17] Add ACPI-based PMT discovery support for Intel PMC David E. Box
  2026-03-25  1:48 ` [PATCH V2 01/17] platform/x86/intel/pmt: Add pre/post decode hooks around header parsing David E. Box
@ 2026-03-25  1:48 ` David E. Box
  2026-03-25  1:48 ` [PATCH V2 03/17] platform/x86/intel/pmt/telemetry: Move overlap check to post-decode hook David E. Box
                   ` (14 subsequent siblings)
  16 siblings, 0 replies; 27+ messages in thread
From: David E. Box @ 2026-03-25  1:48 UTC (permalink / raw)
  To: irenic.rajneesh, ilpo.jarvinen, srinivas.pandruvada, xi.pardee,
	david.e.box
  Cc: hansg, linux-kernel, platform-driver-x86

Refactor crashlog initialization to use the PMT namespace pre-decode hook:

  - Add pmt_crashlog_pre_decode() to parse type/version, select the
    crashlog_info, initialize the control mutex, and set entry->attr_grp.
  - Simplify pmt_crashlog_header_decode() to only read header fields from
    the discovery table.
  - Wire the namespace with .pmt_pre_decode = pmt_crashlog_pre_decode.

This separates structural initialization from header parsing, aligning
crashlog with the PMT class pre/post decode flow.

Signed-off-by: David E. Box <david.e.box@linux.intel.com>
---

V2 - No changes

 drivers/platform/x86/intel/pmt/crashlog.c | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/drivers/platform/x86/intel/pmt/crashlog.c b/drivers/platform/x86/intel/pmt/crashlog.c
index b0393c9c5b4b..f936daf99e4d 100644
--- a/drivers/platform/x86/intel/pmt/crashlog.c
+++ b/drivers/platform/x86/intel/pmt/crashlog.c
@@ -496,11 +496,9 @@ static const struct crashlog_info *select_crashlog_info(u32 type, u32 version)
 	return &crashlog_type1_ver2;
 }
 
-static int pmt_crashlog_header_decode(struct intel_pmt_entry *entry,
-				      struct device *dev)
+static int pmt_crashlog_pre_decode(struct intel_vsec_device *ivdev,
+				   struct intel_pmt_entry *entry)
 {
-	void __iomem *disc_table = entry->disc_table;
-	struct intel_pmt_header *header = &entry->header;
 	struct crashlog_entry *crashlog;
 	u32 version;
 	u32 type;
@@ -513,6 +511,16 @@ static int pmt_crashlog_header_decode(struct intel_pmt_entry *entry,
 	mutex_init(&crashlog->control_mutex);
 
 	crashlog->info = select_crashlog_info(type, version);
+	entry->attr_grp = crashlog->info->attr_grp;
+
+	return 0;
+}
+
+static int pmt_crashlog_header_decode(struct intel_pmt_entry *entry,
+				      struct device *dev)
+{
+	void __iomem *disc_table = entry->disc_table;
+	struct intel_pmt_header *header = &entry->header;
 
 	header->access_type = GET_ACCESS(readl(disc_table));
 	header->guid = readl(disc_table + GUID_OFFSET);
@@ -521,8 +529,6 @@ static int pmt_crashlog_header_decode(struct intel_pmt_entry *entry,
 	/* Size is measured in DWORDS, but accessor returns bytes */
 	header->size = GET_SIZE(readl(disc_table + SIZE_OFFSET));
 
-	entry->attr_grp = crashlog->info->attr_grp;
-
 	return 0;
 }
 
@@ -530,6 +536,7 @@ static DEFINE_XARRAY_ALLOC(crashlog_array);
 static struct intel_pmt_namespace pmt_crashlog_ns = {
 	.name = "crashlog",
 	.xa = &crashlog_array,
+	.pmt_pre_decode = pmt_crashlog_pre_decode,
 	.pmt_header_decode = pmt_crashlog_header_decode,
 };
 
-- 
2.43.0


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

* [PATCH V2 03/17] platform/x86/intel/pmt/telemetry: Move overlap check to post-decode hook
  2026-03-25  1:48 [PATCH V2 00/17] Add ACPI-based PMT discovery support for Intel PMC David E. Box
  2026-03-25  1:48 ` [PATCH V2 01/17] platform/x86/intel/pmt: Add pre/post decode hooks around header parsing David E. Box
  2026-03-25  1:48 ` [PATCH V2 02/17] platform/x86/intel/pmt/crashlog: Split init into pre-decode David E. Box
@ 2026-03-25  1:48 ` David E. Box
  2026-04-07 11:05   ` Ilpo Järvinen
  2026-03-25  1:48 ` [PATCH V2 04/17] platform/x86/intel/pmt: Move header decode into common helper David E. Box
                   ` (13 subsequent siblings)
  16 siblings, 1 reply; 27+ messages in thread
From: David E. Box @ 2026-03-25  1:48 UTC (permalink / raw)
  To: irenic.rajneesh, ilpo.jarvinen, srinivas.pandruvada, xi.pardee,
	david.e.box
  Cc: hansg, linux-kernel, platform-driver-x86

Update the telemetry namespace to use the new PMT class pre/post decode
interface. The overlap check, which previously occurred during header
decode, is now performed in the post-decode hook once header fields are
populated. This preserves existing behavior while reusing the same header
decode logic across PMT drivers.

Signed-off-by: David E. Box <david.e.box@linux.intel.com>
---

V2 - No changes

 drivers/platform/x86/intel/pmt/class.h     |  1 +
 drivers/platform/x86/intel/pmt/telemetry.c | 24 ++++++++++++++--------
 2 files changed, 16 insertions(+), 9 deletions(-)

diff --git a/drivers/platform/x86/intel/pmt/class.h b/drivers/platform/x86/intel/pmt/class.h
index ff39014b208c..8a0db0ef58c1 100644
--- a/drivers/platform/x86/intel/pmt/class.h
+++ b/drivers/platform/x86/intel/pmt/class.h
@@ -37,6 +37,7 @@ struct intel_pmt_header {
 	u32	size;
 	u32	guid;
 	u8	access_type;
+	u8	telem_type;
 };
 
 struct intel_pmt_entry {
diff --git a/drivers/platform/x86/intel/pmt/telemetry.c b/drivers/platform/x86/intel/pmt/telemetry.c
index bdc7c24a3678..d22f633638be 100644
--- a/drivers/platform/x86/intel/pmt/telemetry.c
+++ b/drivers/platform/x86/intel/pmt/telemetry.c
@@ -58,14 +58,9 @@ struct pmt_telem_priv {
 	struct intel_pmt_entry		entry[];
 };
 
-static bool pmt_telem_region_overlaps(struct intel_pmt_entry *entry,
-				      struct device *dev)
+static bool pmt_telem_region_overlaps(struct device *dev, u32 guid, u32 type)
 {
-	u32 guid = readl(entry->disc_table + TELEM_GUID_OFFSET);
-
 	if (intel_pmt_is_early_client_hw(dev)) {
-		u32 type = TELEM_TYPE(readl(entry->disc_table));
-
 		if ((type == TELEM_TYPE_PUNIT_FIXED) ||
 		    (guid == TELEM_CLIENT_FIXED_BLOCK_GUID))
 			return true;
@@ -80,15 +75,25 @@ static int pmt_telem_header_decode(struct intel_pmt_entry *entry,
 	void __iomem *disc_table = entry->disc_table;
 	struct intel_pmt_header *header = &entry->header;
 
-	if (pmt_telem_region_overlaps(entry, dev))
-		return 1;
-
 	header->access_type = TELEM_ACCESS(readl(disc_table));
 	header->guid = readl(disc_table + TELEM_GUID_OFFSET);
 	header->base_offset = readl(disc_table + TELEM_BASE_OFFSET);
 
 	/* Size is measured in DWORDS, but accessor returns bytes */
 	header->size = TELEM_SIZE(readl(disc_table));
+	header->telem_type = TELEM_TYPE(readl(entry->disc_table));
+
+	return 0;
+}
+
+static int pmt_telem_post_decode(struct intel_vsec_device *ivdev,
+				 struct intel_pmt_entry *entry)
+{
+	struct intel_pmt_header *header = &entry->header;
+	struct device *dev = &ivdev->auxdev.dev;
+
+	if (pmt_telem_region_overlaps(dev, header->guid, header->telem_type))
+		return 1;
 
 	/*
 	 * Some devices may expose non-functioning entries that are
@@ -131,6 +136,7 @@ static struct intel_pmt_namespace pmt_telem_ns = {
 	.name = "telem",
 	.xa = &telem_array,
 	.pmt_header_decode = pmt_telem_header_decode,
+	.pmt_post_decode = pmt_telem_post_decode,
 	.pmt_add_endpoint = pmt_telem_add_endpoint,
 };
 
-- 
2.43.0


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

* [PATCH V2 04/17] platform/x86/intel/pmt: Move header decode into common helper
  2026-03-25  1:48 [PATCH V2 00/17] Add ACPI-based PMT discovery support for Intel PMC David E. Box
                   ` (2 preceding siblings ...)
  2026-03-25  1:48 ` [PATCH V2 03/17] platform/x86/intel/pmt/telemetry: Move overlap check to post-decode hook David E. Box
@ 2026-03-25  1:48 ` David E. Box
  2026-04-07 11:05   ` Ilpo Järvinen
  2026-03-25  1:48 ` [PATCH V2 05/17] platform/x86/intel/pmt: Pass discovery index instead of resource David E. Box
                   ` (12 subsequent siblings)
  16 siblings, 1 reply; 27+ messages in thread
From: David E. Box @ 2026-03-25  1:48 UTC (permalink / raw)
  To: irenic.rajneesh, ilpo.jarvinen, srinivas.pandruvada, xi.pardee,
	david.e.box
  Cc: hansg, linux-kernel, platform-driver-x86

Unify PMT discovery table parsing by moving header decode logic into the
class driver. A new helper, pmt_read_header(), now fills in the standard
header fields from the discovery table, replacing the per-namespace
pmt_header_decode callbacks in telemetry and crashlog.

This centralizes the discovery table bit-field definitions in class.h,
removes duplicate decode code from telemetry and crashlog, and prepares the
PMT class for additional discovery sources.

Signed-off-by: David E. Box <david.e.box@linux.intel.com>
---

V2 changes:
- Added PMT_GET_SIZE_BYTES(v), addressing Ilpo feedback on macro naming
  and unit clarity
- Also in PMT_GET_SIZE_BYTES(v) change ((v) << 2) to ((v) * sizeof(u32))
  for clarity
- Removed unused macros from crashlog.c per feedback from Ilpo

 drivers/platform/x86/intel/pmt/class.c     | 37 +++++++++++++++-------
 drivers/platform/x86/intel/pmt/class.h     | 15 +++++++--
 drivers/platform/x86/intel/pmt/crashlog.c  | 23 --------------
 drivers/platform/x86/intel/pmt/telemetry.c | 26 ---------------
 4 files changed, 39 insertions(+), 62 deletions(-)

diff --git a/drivers/platform/x86/intel/pmt/class.c b/drivers/platform/x86/intel/pmt/class.c
index 9b315334a69b..d652b21261f0 100644
--- a/drivers/platform/x86/intel/pmt/class.c
+++ b/drivers/platform/x86/intel/pmt/class.c
@@ -8,6 +8,7 @@
  * Author: "Alexander Duyck" <alexander.h.duyck@linux.intel.com>
  */
 
+#include <linux/bitfield.h>
 #include <linux/kernel.h>
 #include <linux/log2.h>
 #include <linux/intel_vsec.h>
@@ -368,26 +369,40 @@ static int intel_pmt_dev_register(struct intel_pmt_entry *entry,
 	return ret;
 }
 
-int intel_pmt_dev_create(struct intel_pmt_entry *entry, struct intel_pmt_namespace *ns,
-			 struct intel_vsec_device *intel_vsec_dev, int idx)
+static int pmt_read_header(struct intel_vsec_device *ivdev, int idx,
+			   struct intel_pmt_entry *entry)
 {
-	struct device *dev = &intel_vsec_dev->auxdev.dev;
-	struct resource	*disc_res;
-	int ret;
+	struct intel_pmt_header *header = &entry->header;
+	struct device *dev = &ivdev->auxdev.dev;
+	u64 headers[2];
 
-	disc_res = &intel_vsec_dev->resource[idx];
-
-	entry->disc_table = devm_ioremap_resource(dev, disc_res);
+	entry->disc_table = devm_ioremap_resource(dev, &ivdev->resource[idx]);
 	if (IS_ERR(entry->disc_table))
 		return PTR_ERR(entry->disc_table);
 
+	memcpy_fromio(headers, entry->disc_table, 2 * sizeof(u64));
+
+	header->access_type = FIELD_GET(PMT_ACCESS_TYPE, headers[0]);
+	header->telem_type = FIELD_GET(PMT_TELEM_TYPE, headers[0]);
+	header->size = PMT_GET_SIZE_BYTES(headers[0]);
+	header->guid = FIELD_GET(PMT_GUID32, headers[0]);
+	header->base_offset = FIELD_GET(PMT_BASE_OFFSET, headers[1]);
+
+	return 0;
+}
+
+int intel_pmt_dev_create(struct intel_pmt_entry *entry, struct intel_pmt_namespace *ns,
+			 struct intel_vsec_device *intel_vsec_dev, int idx)
+{
+	int ret;
+
 	if (ns->pmt_pre_decode) {
 		ret = ns->pmt_pre_decode(intel_vsec_dev, entry);
 		if (ret)
 			return ret;
 	}
 
-	ret = ns->pmt_header_decode(entry, dev);
+	ret = pmt_read_header(intel_vsec_dev, idx, entry);
 	if (ret)
 		return ret;
 
@@ -397,11 +412,11 @@ int intel_pmt_dev_create(struct intel_pmt_entry *entry, struct intel_pmt_namespa
 			return ret;
 	}
 
-	ret = intel_pmt_populate_entry(entry, intel_vsec_dev, disc_res);
+	ret = intel_pmt_populate_entry(entry, intel_vsec_dev, &intel_vsec_dev->resource[idx]);
 	if (ret)
 		return ret;
 
-	return intel_pmt_dev_register(entry, ns, dev);
+	return intel_pmt_dev_register(entry, ns, &intel_vsec_dev->auxdev.dev);
 }
 EXPORT_SYMBOL_NS_GPL(intel_pmt_dev_create, "INTEL_PMT");
 
diff --git a/drivers/platform/x86/intel/pmt/class.h b/drivers/platform/x86/intel/pmt/class.h
index 8a0db0ef58c1..96ebb15f0053 100644
--- a/drivers/platform/x86/intel/pmt/class.h
+++ b/drivers/platform/x86/intel/pmt/class.h
@@ -11,6 +11,19 @@
 
 #include "telemetry.h"
 
+/* PMT Discovery Table DWORD 1 */
+#define PMT_ACCESS_TYPE		GENMASK_ULL(3, 0)
+#define PMT_TELEM_TYPE		GENMASK_ULL(7, 4)
+#define PMT_SIZE		GENMASK_ULL(27, 12)
+#define PMT_GUID32		GENMASK_ULL(63, 32)
+
+/* PMT Discovery Table DWORD 2 */
+#define PMT_BASE_OFFSET		GENMASK_ULL(31, 0)
+#define PMT_TELE_ID		GENMASK_ULL(63, 32)
+
+/* Convert DWORD size to bytes */
+#define PMT_GET_SIZE_BYTES(h)	((FIELD_GET(PMT_SIZE, h)) * sizeof(u32))
+
 /* PMT access types */
 #define ACCESS_BARID		2
 #define ACCESS_LOCAL		3
@@ -61,8 +74,6 @@ struct intel_pmt_entry {
 struct intel_pmt_namespace {
 	const char *name;
 	struct xarray *xa;
-	int (*pmt_header_decode)(struct intel_pmt_entry *entry,
-				 struct device *dev);
 	int (*pmt_pre_decode)(struct intel_vsec_device *ivdev,
 			      struct intel_pmt_entry *entry);
 	int (*pmt_post_decode)(struct intel_vsec_device *ivdev,
diff --git a/drivers/platform/x86/intel/pmt/crashlog.c b/drivers/platform/x86/intel/pmt/crashlog.c
index f936daf99e4d..ef1826b15cf4 100644
--- a/drivers/platform/x86/intel/pmt/crashlog.c
+++ b/drivers/platform/x86/intel/pmt/crashlog.c
@@ -26,14 +26,8 @@
 
 /* Crashlog Discovery Header */
 #define CONTROL_OFFSET		0x0
-#define GUID_OFFSET		0x4
-#define BASE_OFFSET		0x8
-#define SIZE_OFFSET		0xC
-#define GET_ACCESS(v)		((v) & GENMASK(3, 0))
 #define GET_TYPE(v)		(((v) & GENMASK(7, 4)) >> 4)
 #define GET_VERSION(v)		(((v) & GENMASK(19, 16)) >> 16)
-/* size is in bytes */
-#define GET_SIZE(v)		((v) * sizeof(u32))
 
 /*
  * Type 1 Version 0
@@ -516,28 +510,11 @@ static int pmt_crashlog_pre_decode(struct intel_vsec_device *ivdev,
 	return 0;
 }
 
-static int pmt_crashlog_header_decode(struct intel_pmt_entry *entry,
-				      struct device *dev)
-{
-	void __iomem *disc_table = entry->disc_table;
-	struct intel_pmt_header *header = &entry->header;
-
-	header->access_type = GET_ACCESS(readl(disc_table));
-	header->guid = readl(disc_table + GUID_OFFSET);
-	header->base_offset = readl(disc_table + BASE_OFFSET);
-
-	/* Size is measured in DWORDS, but accessor returns bytes */
-	header->size = GET_SIZE(readl(disc_table + SIZE_OFFSET));
-
-	return 0;
-}
-
 static DEFINE_XARRAY_ALLOC(crashlog_array);
 static struct intel_pmt_namespace pmt_crashlog_ns = {
 	.name = "crashlog",
 	.xa = &crashlog_array,
 	.pmt_pre_decode = pmt_crashlog_pre_decode,
-	.pmt_header_decode = pmt_crashlog_header_decode,
 };
 
 /*
diff --git a/drivers/platform/x86/intel/pmt/telemetry.c b/drivers/platform/x86/intel/pmt/telemetry.c
index d22f633638be..80773e3c3efa 100644
--- a/drivers/platform/x86/intel/pmt/telemetry.c
+++ b/drivers/platform/x86/intel/pmt/telemetry.c
@@ -27,14 +27,6 @@
 
 #include "class.h"
 
-#define TELEM_SIZE_OFFSET	0x0
-#define TELEM_GUID_OFFSET	0x4
-#define TELEM_BASE_OFFSET	0x8
-#define TELEM_ACCESS(v)		((v) & GENMASK(3, 0))
-#define TELEM_TYPE(v)		(((v) & GENMASK(7, 4)) >> 4)
-/* size is in bytes */
-#define TELEM_SIZE(v)		(((v) & GENMASK(27, 12)) >> 10)
-
 /* Used by client hardware to identify a fixed telemetry entry*/
 #define TELEM_CLIENT_FIXED_BLOCK_GUID	0x10000000
 
@@ -69,23 +61,6 @@ static bool pmt_telem_region_overlaps(struct device *dev, u32 guid, u32 type)
 	return false;
 }
 
-static int pmt_telem_header_decode(struct intel_pmt_entry *entry,
-				   struct device *dev)
-{
-	void __iomem *disc_table = entry->disc_table;
-	struct intel_pmt_header *header = &entry->header;
-
-	header->access_type = TELEM_ACCESS(readl(disc_table));
-	header->guid = readl(disc_table + TELEM_GUID_OFFSET);
-	header->base_offset = readl(disc_table + TELEM_BASE_OFFSET);
-
-	/* Size is measured in DWORDS, but accessor returns bytes */
-	header->size = TELEM_SIZE(readl(disc_table));
-	header->telem_type = TELEM_TYPE(readl(entry->disc_table));
-
-	return 0;
-}
-
 static int pmt_telem_post_decode(struct intel_vsec_device *ivdev,
 				 struct intel_pmt_entry *entry)
 {
@@ -135,7 +110,6 @@ static DEFINE_XARRAY_ALLOC(telem_array);
 static struct intel_pmt_namespace pmt_telem_ns = {
 	.name = "telem",
 	.xa = &telem_array,
-	.pmt_header_decode = pmt_telem_header_decode,
 	.pmt_post_decode = pmt_telem_post_decode,
 	.pmt_add_endpoint = pmt_telem_add_endpoint,
 };
-- 
2.43.0


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

* [PATCH V2 05/17] platform/x86/intel/pmt: Pass discovery index instead of resource
  2026-03-25  1:48 [PATCH V2 00/17] Add ACPI-based PMT discovery support for Intel PMC David E. Box
                   ` (3 preceding siblings ...)
  2026-03-25  1:48 ` [PATCH V2 04/17] platform/x86/intel/pmt: Move header decode into common helper David E. Box
@ 2026-03-25  1:48 ` David E. Box
  2026-04-07 11:07   ` Ilpo Järvinen
  2026-03-25  1:48 ` [PATCH V2 06/17] platform/x86/intel/pmt: Unify header fetch and add ACPI source David E. Box
                   ` (11 subsequent siblings)
  16 siblings, 1 reply; 27+ messages in thread
From: David E. Box @ 2026-03-25  1:48 UTC (permalink / raw)
  To: irenic.rajneesh, ilpo.jarvinen, srinivas.pandruvada, xi.pardee,
	david.e.box
  Cc: hansg, linux-kernel, platform-driver-x86

Change PMT class code to pass a discovery index rather than a direct struct
resource when creating entries. This allows the class to identify the
discovery source generically without assuming PCI BAR resources. For PCI
devices, the index still resolves to a resource in the intel_vsec_device.
Other discovery sources, such as ACPI, can use the same index without
needing a struct resource.

Signed-off-by: David E. Box <david.e.box@linux.intel.com>
---

V2 - No changes

 drivers/platform/x86/intel/pmt/class.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/platform/x86/intel/pmt/class.c b/drivers/platform/x86/intel/pmt/class.c
index d652b21261f0..3fcea6a6e763 100644
--- a/drivers/platform/x86/intel/pmt/class.c
+++ b/drivers/platform/x86/intel/pmt/class.c
@@ -207,11 +207,12 @@ EXPORT_SYMBOL_GPL(intel_pmt_class);
 
 static int intel_pmt_populate_entry(struct intel_pmt_entry *entry,
 				    struct intel_vsec_device *ivdev,
-				    struct resource *disc_res)
+				    int idx)
 {
 	struct pci_dev *pci_dev = to_pci_dev(ivdev->dev);
 	struct device *dev = &ivdev->auxdev.dev;
 	struct intel_pmt_header *header = &entry->header;
+	struct resource *disc_res;
 	u8 bir;
 
 	/*
@@ -236,6 +237,7 @@ static int intel_pmt_populate_entry(struct intel_pmt_entry *entry,
 		 * For access_type LOCAL, the base address is as follows:
 		 * base address = end of discovery region + base offset
 		 */
+		disc_res = &ivdev->resource[idx];
 		entry->base_addr = disc_res->end + 1 + header->base_offset;
 
 		/*
@@ -412,7 +414,7 @@ int intel_pmt_dev_create(struct intel_pmt_entry *entry, struct intel_pmt_namespa
 			return ret;
 	}
 
-	ret = intel_pmt_populate_entry(entry, intel_vsec_dev, &intel_vsec_dev->resource[idx]);
+	ret = intel_pmt_populate_entry(entry, intel_vsec_dev, idx);
 	if (ret)
 		return ret;
 
-- 
2.43.0


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

* [PATCH V2 06/17] platform/x86/intel/pmt: Unify header fetch and add ACPI source
  2026-03-25  1:48 [PATCH V2 00/17] Add ACPI-based PMT discovery support for Intel PMC David E. Box
                   ` (4 preceding siblings ...)
  2026-03-25  1:48 ` [PATCH V2 05/17] platform/x86/intel/pmt: Pass discovery index instead of resource David E. Box
@ 2026-03-25  1:48 ` David E. Box
  2026-04-07 12:14   ` Ilpo Järvinen
  2026-03-25  1:48 ` [PATCH V2 07/17] platform/x86/intel/pmc: Add PMC SSRAM Kconfig description David E. Box
                   ` (10 subsequent siblings)
  16 siblings, 1 reply; 27+ messages in thread
From: David E. Box @ 2026-03-25  1:48 UTC (permalink / raw)
  To: irenic.rajneesh, ilpo.jarvinen, srinivas.pandruvada, xi.pardee,
	david.e.box
  Cc: hansg, linux-kernel, platform-driver-x86

Allow the PMT class to read discovery headers from either PCI MMIO or
ACPI-provided entries, depending on the discovery source. The new
source-aware fetch helper retrieves the first two QWORDs for both paths
while keeping the mapped discovery table available for users such as
crashlog.

Split intel_pmt_populate_entry() into source-specific resolvers:
  - pmt_resolve_access_pci(): handles both ACCESS_LOCAL and ACCESS_BARID
    for PCI-backed devices and sets entry->pcidev. Same existing
    functionality.
  - pmt_resolve_access_acpi(): handles only ACCESS_BARID for ACPI-backed
    devices, rejecting ACCESS_LOCAL which has no valid semantics without
    a physical discovery resource.

This maintains existing PCI behavior and makes no functional changes
for PCI devices.

Signed-off-by: David E. Box <david.e.box@linux.intel.com>
---

V2 changes:
- In pmt_resolve_access_acpi(), moved dev_err() call to single line
  instead of split across two lines
- Restructured error handling in intel_pmt_populate_entry(), moving error
  returns from after switch/case into each case statement for better
  readability
- Addressed Ilpo's feedback on error message formatting and error
  handling patterns

 drivers/platform/x86/intel/pmt/class.c | 123 +++++++++++++++++++++++--
 1 file changed, 114 insertions(+), 9 deletions(-)

diff --git a/drivers/platform/x86/intel/pmt/class.c b/drivers/platform/x86/intel/pmt/class.c
index 3fcea6a6e763..64678f55a20e 100644
--- a/drivers/platform/x86/intel/pmt/class.c
+++ b/drivers/platform/x86/intel/pmt/class.c
@@ -205,9 +205,9 @@ struct class intel_pmt_class = {
 };
 EXPORT_SYMBOL_GPL(intel_pmt_class);
 
-static int intel_pmt_populate_entry(struct intel_pmt_entry *entry,
-				    struct intel_vsec_device *ivdev,
-				    int idx)
+static int pmt_resolve_access_pci(struct intel_pmt_entry *entry,
+				  struct intel_vsec_device *ivdev,
+				  int idx)
 {
 	struct pci_dev *pci_dev = to_pci_dev(ivdev->dev);
 	struct device *dev = &ivdev->auxdev.dev;
@@ -287,6 +287,81 @@ static int intel_pmt_populate_entry(struct intel_pmt_entry *entry,
 	}
 
 	entry->pcidev = pci_dev;
+
+	return 0;
+}
+
+static int pmt_resolve_access_acpi(struct intel_pmt_entry *entry,
+				   struct intel_vsec_device *ivdev)
+{
+	struct pci_dev *pci_dev = NULL;
+	struct device *dev = &ivdev->auxdev.dev;
+	struct intel_pmt_header *header = &entry->header;
+	u8 bir;
+
+	if (dev_is_pci(ivdev->dev))
+		pci_dev = to_pci_dev(ivdev->dev);
+
+	/*
+	 * The base offset should always be 8 byte aligned.
+	 *
+	 * For non-local access types the lower 3 bits of base offset
+	 * contains the index of the base address register where the
+	 * telemetry can be found.
+	 */
+	bir = GET_BIR(header->base_offset);
+
+	switch (header->access_type) {
+	case ACCESS_BARID:
+		/* ACPI platform drivers use base_addr */
+		if (ivdev->base_addr) {
+			entry->base_addr = ivdev->base_addr +
+					   GET_ADDRESS(header->base_offset);
+			break;
+		}
+
+		/* If base_addr is not provided, then this is an ACPI companion device */
+		if (!pci_dev) {
+			dev_err(dev, "ACCESS_BARID requires PCI BAR resources or base_addr\n");
+			return -EINVAL;
+		}
+
+		entry->base_addr = pci_resource_start(pci_dev, bir) +
+			GET_ADDRESS(header->base_offset);
+		break;
+	default:
+		dev_err(dev, "Unsupported access type %d for ACPI based PMT\n",
+			header->access_type);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int intel_pmt_populate_entry(struct intel_pmt_entry *entry,
+				    struct intel_vsec_device *ivdev,
+				    int idx)
+{
+	struct intel_pmt_header *header = &entry->header;
+	struct device *dev = &ivdev->auxdev.dev;
+	int ret;
+
+	switch (ivdev->src) {
+	case INTEL_VSEC_DISC_PCI:
+		ret = pmt_resolve_access_pci(entry, ivdev, idx);
+		if (ret)
+			return ret;
+		break;
+	case INTEL_VSEC_DISC_ACPI:
+		ret = pmt_resolve_access_acpi(entry, ivdev);
+		if (ret)
+			return ret;
+		break;
+	default:
+		dev_err(dev, "Unknown discovery source: %d\n", ivdev->src);
+		return -EINVAL;
+	}
+
 	entry->guid = header->guid;
 	entry->size = header->size;
 	entry->cb = ivdev->priv_data;
@@ -371,18 +446,48 @@ static int intel_pmt_dev_register(struct intel_pmt_entry *entry,
 	return ret;
 }
 
+static int pmt_get_headers(struct intel_vsec_device *ivdev, int idx,
+			   struct intel_pmt_entry *entry, u64 headers[2])
+{
+	struct device *dev = &ivdev->auxdev.dev;
+
+	switch (ivdev->src) {
+	case INTEL_VSEC_DISC_PCI: {
+		void __iomem *disc_table;
+
+		disc_table = devm_ioremap_resource(dev, &ivdev->resource[idx]);
+		if (IS_ERR(disc_table))
+			return PTR_ERR(disc_table);
+
+		memcpy_fromio(headers, disc_table, 2 * sizeof(u64));
+
+		/* Used by crashlog driver */
+		entry->disc_table = disc_table;
+
+		return 0;
+	}
+	case INTEL_VSEC_DISC_ACPI:
+		memcpy(headers, &ivdev->acpi_disc[idx][0], 2 * sizeof(u64));
+
+		return 0;
+	default:
+		dev_err(dev, "Unknown discovery source type: %d\n", ivdev->src);
+		break;
+	}
+
+	return -EINVAL;
+}
+
 static int pmt_read_header(struct intel_vsec_device *ivdev, int idx,
 			   struct intel_pmt_entry *entry)
 {
 	struct intel_pmt_header *header = &entry->header;
-	struct device *dev = &ivdev->auxdev.dev;
 	u64 headers[2];
+	int ret;
 
-	entry->disc_table = devm_ioremap_resource(dev, &ivdev->resource[idx]);
-	if (IS_ERR(entry->disc_table))
-		return PTR_ERR(entry->disc_table);
-
-	memcpy_fromio(headers, entry->disc_table, 2 * sizeof(u64));
+	ret = pmt_get_headers(ivdev, idx, entry, headers);
+	if (ret)
+		return ret;
 
 	header->access_type = FIELD_GET(PMT_ACCESS_TYPE, headers[0]);
 	header->telem_type = FIELD_GET(PMT_TELEM_TYPE, headers[0]);
-- 
2.43.0


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

* [PATCH V2 07/17] platform/x86/intel/pmc: Add PMC SSRAM Kconfig description
  2026-03-25  1:48 [PATCH V2 00/17] Add ACPI-based PMT discovery support for Intel PMC David E. Box
                   ` (5 preceding siblings ...)
  2026-03-25  1:48 ` [PATCH V2 06/17] platform/x86/intel/pmt: Unify header fetch and add ACPI source David E. Box
@ 2026-03-25  1:48 ` David E. Box
  2026-04-07 12:16   ` Ilpo Järvinen
  2026-03-25  1:48 ` [PATCH V2 08/17] platform/x86/intel/pmc: Add ACPI PWRM telemetry driver for Nova Lake S David E. Box
                   ` (9 subsequent siblings)
  16 siblings, 1 reply; 27+ messages in thread
From: David E. Box @ 2026-03-25  1:48 UTC (permalink / raw)
  To: irenic.rajneesh, ilpo.jarvinen, srinivas.pandruvada, xi.pardee,
	david.e.box
  Cc: hansg, linux-kernel, platform-driver-x86

Add a proper description for the intel_pmc_ssram driver.

Signed-off-by: David E. Box <david.e.box@linux.intel.com>
---

V2 - No changes

 drivers/platform/x86/intel/pmc/Kconfig | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/platform/x86/intel/pmc/Kconfig b/drivers/platform/x86/intel/pmc/Kconfig
index c6ef0bcf76af..0f19dc7edcf9 100644
--- a/drivers/platform/x86/intel/pmc/Kconfig
+++ b/drivers/platform/x86/intel/pmc/Kconfig
@@ -28,3 +28,14 @@ config INTEL_PMC_CORE
 
 config INTEL_PMC_SSRAM_TELEMETRY
 	tristate
+	help
+	  This PCI driver discovers PMC SSRAM telemetry regions through the
+	  PMC's MMIO interface and registers them with the Intel VSEC framework
+	  as Intel PMT telemetry devices.
+
+	  It probes the PMC SSRAM device, extracts DVSEC information from MMIO,
+	  reads device IDs and base addresses for multiple PMCs (main, IOE, PCH),
+	  and exposes the discovered telemetry through Intel PMT interfaces
+	  (including sysfs).
+
+	  This option is selected by INTEL_PMC_CORE.
-- 
2.43.0


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

* [PATCH V2 08/17] platform/x86/intel/pmc: Add ACPI PWRM telemetry driver for Nova Lake S
  2026-03-25  1:48 [PATCH V2 00/17] Add ACPI-based PMT discovery support for Intel PMC David E. Box
                   ` (6 preceding siblings ...)
  2026-03-25  1:48 ` [PATCH V2 07/17] platform/x86/intel/pmc: Add PMC SSRAM Kconfig description David E. Box
@ 2026-03-25  1:48 ` David E. Box
  2026-04-07 12:56   ` Ilpo Järvinen
  2026-03-25  1:48 ` [PATCH V2 09/17] platform/x86/intel/pmc/ssram: Rename probe and PCI ID table for consistency David E. Box
                   ` (8 subsequent siblings)
  16 siblings, 1 reply; 27+ messages in thread
From: David E. Box @ 2026-03-25  1:48 UTC (permalink / raw)
  To: irenic.rajneesh, ilpo.jarvinen, srinivas.pandruvada, xi.pardee,
	david.e.box
  Cc: hansg, linux-kernel, platform-driver-x86

Add an ACPI-based PMC PWRM telemetry driver for Nova Lake S. The driver
locates PMT discovery data in _DSD under the Intel VSEC UUID, parses it,
and registers telemetry regions with the PMT/VSEC framework so PMC
telemetry is exposed via existing PMT interfaces.

Export pmc_parse_telem_dsd() and pmc_find_telem_guid() to support ACPI
discovery in other PMC drivers (e.g., ssram_telemetry) without duplicating
ACPI parsing logic. Also export acpi_disc_t typedef from core.h for callers
to properly declare discovery table arrays.

Selected by INTEL_PMC_CORE. Existing PCI functionality is preserved.

Signed-off-by: David E. Box <david.e.box@linux.intel.com>
---

V2 changes:
- Added explicit <linux/uuid.h> include for guid_t type availability in
  core.h
- Added explicit <linux/bits.h> include in pwrm_telemetry.c for GENMASK()
- Added <linux/cleanup.h> and converted goto based cleanup to __free()
  attributes per Ilpo's feedback
- Combined u64 hdr0 and u64 hdr1 into single declaration
- Converted pmc_parse_telem_dsd() to return acpi_disc directly with
  ERR_PTR() for failures
- Added braces around _DSD evaluation failure path

 drivers/platform/x86/intel/pmc/Kconfig        |  14 ++
 drivers/platform/x86/intel/pmc/Makefile       |   2 +
 drivers/platform/x86/intel/pmc/core.h         |  15 ++
 .../platform/x86/intel/pmc/pwrm_telemetry.c   | 214 ++++++++++++++++++
 4 files changed, 245 insertions(+)
 create mode 100644 drivers/platform/x86/intel/pmc/pwrm_telemetry.c

diff --git a/drivers/platform/x86/intel/pmc/Kconfig b/drivers/platform/x86/intel/pmc/Kconfig
index 0f19dc7edcf9..937186b0b5dd 100644
--- a/drivers/platform/x86/intel/pmc/Kconfig
+++ b/drivers/platform/x86/intel/pmc/Kconfig
@@ -9,6 +9,7 @@ config INTEL_PMC_CORE
 	depends on ACPI
 	depends on INTEL_PMT_TELEMETRY
 	select INTEL_PMC_SSRAM_TELEMETRY
+	select INTEL_PMC_PWRM_TELEMETRY
 	help
 	  The Intel Platform Controller Hub for Intel Core SoCs provides access
 	  to Power Management Controller registers via various interfaces. This
@@ -39,3 +40,16 @@ config INTEL_PMC_SSRAM_TELEMETRY
 	  (including sysfs).
 
 	  This option is selected by INTEL_PMC_CORE.
+
+config INTEL_PMC_PWRM_TELEMETRY
+	tristate
+	help
+	  This driver discovers PMC PWRM telemetry regions described in ACPI
+	  _DSD and registers them with the Intel VSEC framework as Intel PMT
+	  telemetry devices.
+
+	  It validates the ACPI discovery data and publishes the discovered
+	  regions so they can be accessed through the Intel PMT telemetry
+	  interfaces (including sysfs).
+
+	  This option is selected by INTEL_PMC_CORE.
diff --git a/drivers/platform/x86/intel/pmc/Makefile b/drivers/platform/x86/intel/pmc/Makefile
index bb960c8721d7..fdbb768f7b09 100644
--- a/drivers/platform/x86/intel/pmc/Makefile
+++ b/drivers/platform/x86/intel/pmc/Makefile
@@ -12,3 +12,5 @@ obj-$(CONFIG_INTEL_PMC_CORE)		+= intel_pmc_core_pltdrv.o
 # Intel PMC SSRAM driver
 intel_pmc_ssram_telemetry-y		+= ssram_telemetry.o
 obj-$(CONFIG_INTEL_PMC_SSRAM_TELEMETRY)	+= intel_pmc_ssram_telemetry.o
+intel_pmc_pwrm_telemetry-y		+= pwrm_telemetry.o
+obj-$(CONFIG_INTEL_PMC_PWRM_TELEMETRY)	+= intel_pmc_pwrm_telemetry.o
diff --git a/drivers/platform/x86/intel/pmc/core.h b/drivers/platform/x86/intel/pmc/core.h
index 118c8740ad3a..37ea1caf1817 100644
--- a/drivers/platform/x86/intel/pmc/core.h
+++ b/drivers/platform/x86/intel/pmc/core.h
@@ -14,10 +14,14 @@
 
 #include <linux/acpi.h>
 #include <linux/bits.h>
+#include <linux/cleanup.h>
 #include <linux/platform_device.h>
+#include <linux/uuid.h>
 
 struct telem_endpoint;
 
+DEFINE_FREE(pmc_acpi_free, void *, if (_T) ACPI_FREE(_T))
+
 #define SLP_S0_RES_COUNTER_MASK			GENMASK(31, 0)
 
 #define PMC_BASE_ADDR_DEFAULT			0xFE000000
@@ -562,6 +566,8 @@ 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;
 
+extern const guid_t intel_vsec_guid;
+
 #define pmc_for_each_mode(mode, pmc)						\
 	for (unsigned int __i = 0, __cond;					\
 	     __cond = __i < (pmc)->num_lpm_modes,				\
@@ -583,4 +589,13 @@ static const struct file_operations __name ## _fops = {			\
 	.release	= single_release,				\
 }
 
+struct intel_vsec_header;
+union acpi_object;
+
+/* Avoid checkpatch warning */
+typedef u32 (*acpi_disc_t)[4];
+
+ acpi_disc_t pmc_parse_telem_dsd(union acpi_object *obj,
+			 struct intel_vsec_header *header);
+union acpi_object *pmc_find_telem_guid(union acpi_object *dsd);
 #endif /* PMC_CORE_H */
diff --git a/drivers/platform/x86/intel/pmc/pwrm_telemetry.c b/drivers/platform/x86/intel/pmc/pwrm_telemetry.c
new file mode 100644
index 000000000000..e852ee2d6d9f
--- /dev/null
+++ b/drivers/platform/x86/intel/pmc/pwrm_telemetry.c
@@ -0,0 +1,214 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Intel PMC PWRM ACPI driver
+ *
+ * Copyright (C) 2025, Intel Corporation
+ */
+
+#include <linux/acpi.h>
+#include <linux/bits.h>
+#include <linux/bitfield.h>
+#include <linux/cleanup.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/intel_vsec.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/resource.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/uuid.h>
+
+#include "core.h"
+
+#define ENTRY_LEN		5
+
+/* DWORD2 */
+#define DVSEC_ID_MASK		GENMASK(15, 0)
+#define NUM_ENTRIES_MASK	GENMASK(23, 16)
+#define ENTRY_SIZE_MASK		GENMASK(31, 24)
+
+/* DWORD3 */
+#define TBIR_MASK		GENMASK(2, 0)
+#define DISC_TBL_OFF_MASK	GENMASK(31, 3)
+
+const guid_t intel_vsec_guid =
+	GUID_INIT(0x294903fb, 0x634d, 0x4fc7, 0xaf, 0x1f, 0x0f, 0xb9,
+		  0x56, 0xb0, 0x4f, 0xc1);
+
+static bool is_valid_entry(union acpi_object *pkg)
+{
+	int i;
+
+	if (!pkg || pkg->type != ACPI_TYPE_PACKAGE || pkg->package.count != ENTRY_LEN)
+		return false;
+
+	if (pkg->package.elements[0].type != ACPI_TYPE_STRING)
+		return false;
+
+	for (i = 1; i < ENTRY_LEN; i++)
+		if (pkg->package.elements[i].type != ACPI_TYPE_INTEGER)
+			return false;
+
+	return true;
+}
+
+u32 (*pmc_parse_telem_dsd(union acpi_object *obj,
+			  struct intel_vsec_header *header))[4]
+{
+	acpi_disc_t disc __free(kfree) = NULL;
+	union acpi_object *vsec_pkg;
+	union acpi_object *disc_pkg;
+	u64 hdr0, hdr1;
+	int num_regions;
+	int i;
+
+	if (!header)
+		return ERR_PTR(-EINVAL);
+
+	if (!obj || obj->type != ACPI_TYPE_PACKAGE || obj->package.count != 2)
+		return ERR_PTR(-EINVAL);
+
+	/* First Package is DVSEC info */
+	vsec_pkg = &obj->package.elements[0];
+	if (!is_valid_entry(vsec_pkg))
+		return ERR_PTR(-EINVAL);
+
+	hdr0 = vsec_pkg->package.elements[3].integer.value;
+	hdr1 = vsec_pkg->package.elements[4].integer.value;
+
+	header->id          = FIELD_GET(DVSEC_ID_MASK, hdr0);
+	header->num_entries = FIELD_GET(NUM_ENTRIES_MASK, hdr0);
+	header->entry_size  = FIELD_GET(ENTRY_SIZE_MASK, hdr0);
+	header->tbir        = FIELD_GET(TBIR_MASK, hdr1);
+	header->offset      = FIELD_GET(DISC_TBL_OFF_MASK, hdr1);
+
+	/* Second Package contains the discovery tables */
+	disc_pkg = &obj->package.elements[1];
+	if (disc_pkg->type != ACPI_TYPE_PACKAGE || disc_pkg->package.count < 1)
+		return ERR_PTR(-EINVAL);
+
+	num_regions = disc_pkg->package.count;
+	if (header->num_entries != num_regions)
+		return ERR_PTR(-EINVAL);
+
+	disc = kmalloc_array(num_regions, sizeof(*disc), GFP_KERNEL);
+	if (!disc)
+		return ERR_PTR(-ENOMEM);
+
+	for (i = 0; i < num_regions; i++) {
+		union acpi_object *pkg;
+		u64 value;
+		int j;
+
+		pkg = &disc_pkg->package.elements[i];
+		if (!is_valid_entry(pkg))
+			return ERR_PTR(-EINVAL);
+
+		/* Element 0 is a descriptive string; DWORD values start at index 1. */
+		for (j = 1; j < ENTRY_LEN; j++) {
+			value = pkg->package.elements[j].integer.value;
+			if (value > U32_MAX)
+				return ERR_PTR(-ERANGE);
+
+			disc[i][j - 1] = value;
+		}
+	}
+
+	return no_free_ptr(disc);
+}
+EXPORT_SYMBOL_NS_GPL(pmc_parse_telem_dsd, "INTEL_PMC_CORE");
+
+union acpi_object *pmc_find_telem_guid(union acpi_object *dsd)
+{
+	int i;
+
+	if (!dsd || dsd->type != ACPI_TYPE_PACKAGE)
+		return NULL;
+
+	for (i = 0; i + 1 < dsd->package.count; i += 2) {
+		union acpi_object *uuid_obj, *data_obj;
+		guid_t uuid;
+
+		uuid_obj = &dsd->package.elements[i];
+		data_obj = &dsd->package.elements[i + 1];
+
+		if (uuid_obj->type != ACPI_TYPE_BUFFER ||
+		    uuid_obj->buffer.length != 16)
+			continue;
+
+		memcpy(&uuid, uuid_obj->buffer.pointer, 16);
+		if (guid_equal(&uuid, &intel_vsec_guid))
+			return data_obj;
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL_NS_GPL(pmc_find_telem_guid, "INTEL_PMC_CORE");
+
+static int pmc_pwrm_acpi_probe(struct platform_device *pdev)
+{
+	struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
+	acpi_handle handle = ACPI_HANDLE(&pdev->dev);
+	struct intel_vsec_header header;
+	struct intel_vsec_header *headers[2] = { &header, NULL };
+	struct intel_vsec_platform_info info = { };
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	union acpi_object *dsd;
+	acpi_status status;
+
+	if (!handle)
+		return -ENODEV;
+
+	status = acpi_evaluate_object(handle, "_DSD", NULL, &buf);
+	if (ACPI_FAILURE(status)) {
+		return dev_err_probe(dev, -ENODEV, "Could not evaluate _DSD: %s\n",
+				     acpi_format_exception(status));
+	}
+
+	void *dsd_buf __free(pmc_acpi_free) = buf.pointer;
+
+	dsd = pmc_find_telem_guid(dsd_buf);
+	if (!dsd)
+		return -ENODEV;
+
+	acpi_disc_t acpi_disc __free(kfree) = pmc_parse_telem_dsd(dsd, &header);
+	if (IS_ERR(acpi_disc))
+		return PTR_ERR(acpi_disc);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, header.tbir);
+	if (!res)
+		return -EINVAL;
+
+	info.headers = headers;
+	info.caps = VSEC_CAP_TELEMETRY;
+	info.acpi_disc = acpi_disc;
+	info.src = INTEL_VSEC_DISC_ACPI;
+	info.base_addr = res->start;
+
+	return intel_vsec_register(&pdev->dev, &info);
+}
+
+static const struct acpi_device_id pmc_pwrm_acpi_ids[] = {
+	{ "INTC1122", 0 }, /* Nova Lake */
+	{ "INTC1129", 0 }, /* Nova Lake */
+	{ }
+};
+MODULE_DEVICE_TABLE(acpi, pmc_pwrm_acpi_ids);
+
+static struct platform_driver pmc_pwrm_acpi_driver = {
+	.probe = pmc_pwrm_acpi_probe,
+	.driver = {
+		.name = "intel_pmc_pwrm_acpi",
+		.acpi_match_table = ACPI_PTR(pmc_pwrm_acpi_ids),
+	},
+};
+module_platform_driver(pmc_pwrm_acpi_driver);
+
+MODULE_AUTHOR("David E. Box <david.e.box@linux.intel.com>");
+MODULE_DESCRIPTION("Intel PMC PWRM ACPI driver");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("INTEL_VSEC");
-- 
2.43.0


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

* [PATCH V2 09/17] platform/x86/intel/pmc/ssram: Rename probe and PCI ID table for consistency
  2026-03-25  1:48 [PATCH V2 00/17] Add ACPI-based PMT discovery support for Intel PMC David E. Box
                   ` (7 preceding siblings ...)
  2026-03-25  1:48 ` [PATCH V2 08/17] platform/x86/intel/pmc: Add ACPI PWRM telemetry driver for Nova Lake S David E. Box
@ 2026-03-25  1:48 ` David E. Box
  2026-03-25  1:48 ` [PATCH V2 10/17] platform/x86/intel/pmc/ssram: Use fixed-size static pmc array David E. Box
                   ` (7 subsequent siblings)
  16 siblings, 0 replies; 27+ messages in thread
From: David E. Box @ 2026-03-25  1:48 UTC (permalink / raw)
  To: irenic.rajneesh, ilpo.jarvinen, srinivas.pandruvada, xi.pardee,
	david.e.box
  Cc: hansg, linux-kernel, platform-driver-x86

Rename intel_pmc_ssram_telemetry_probe() to pmc_ssram_telemetry_probe() and
intel_pmc_ssram_telemetry_pci_ids[] to pmc_ssram_telemetry_pci_ids[],
updating the MODULE_DEVICE_TABLE() and pci_driver wiring accordingly.

This aligns the symbol names with the driver filename and module name,
reduces redundant intel_ prefixes, and improves readability. No functional
behavior changes are intended.

Signed-off-by: David E. Box <david.e.box@linux.intel.com>
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---

V2 - No changes

 drivers/platform/x86/intel/pmc/ssram_telemetry.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/platform/x86/intel/pmc/ssram_telemetry.c b/drivers/platform/x86/intel/pmc/ssram_telemetry.c
index 6f6e83e70fc5..1deb4d71da3f 100644
--- a/drivers/platform/x86/intel/pmc/ssram_telemetry.c
+++ b/drivers/platform/x86/intel/pmc/ssram_telemetry.c
@@ -149,7 +149,7 @@ int pmc_ssram_telemetry_get_pmc_info(unsigned int pmc_idx,
 }
 EXPORT_SYMBOL_GPL(pmc_ssram_telemetry_get_pmc_info);
 
-static int intel_pmc_ssram_telemetry_probe(struct pci_dev *pcidev, const struct pci_device_id *id)
+static int pmc_ssram_telemetry_probe(struct pci_dev *pcidev, const struct pci_device_id *id)
 {
 	int ret;
 
@@ -183,7 +183,7 @@ static int intel_pmc_ssram_telemetry_probe(struct pci_dev *pcidev, const struct
 	return ret;
 }
 
-static const struct pci_device_id intel_pmc_ssram_telemetry_pci_ids[] = {
+static const struct pci_device_id pmc_ssram_telemetry_pci_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PMC_DEVID_MTL_SOCM) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PMC_DEVID_ARL_SOCS) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PMC_DEVID_ARL_SOCM) },
@@ -193,14 +193,14 @@ static const struct pci_device_id intel_pmc_ssram_telemetry_pci_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PMC_DEVID_WCL_PCDN) },
 	{ }
 };
-MODULE_DEVICE_TABLE(pci, intel_pmc_ssram_telemetry_pci_ids);
+MODULE_DEVICE_TABLE(pci, pmc_ssram_telemetry_pci_ids);
 
-static struct pci_driver intel_pmc_ssram_telemetry_driver = {
+static struct pci_driver pmc_ssram_telemetry_driver = {
 	.name = "intel_pmc_ssram_telemetry",
-	.id_table = intel_pmc_ssram_telemetry_pci_ids,
-	.probe = intel_pmc_ssram_telemetry_probe,
+	.id_table = pmc_ssram_telemetry_pci_ids,
+	.probe = pmc_ssram_telemetry_probe,
 };
-module_pci_driver(intel_pmc_ssram_telemetry_driver);
+module_pci_driver(pmc_ssram_telemetry_driver);
 
 MODULE_IMPORT_NS("INTEL_VSEC");
 MODULE_AUTHOR("Xi Pardee <xi.pardee@intel.com>");
-- 
2.43.0


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

* [PATCH V2 10/17] platform/x86/intel/pmc/ssram: Use fixed-size static pmc array
  2026-03-25  1:48 [PATCH V2 00/17] Add ACPI-based PMT discovery support for Intel PMC David E. Box
                   ` (8 preceding siblings ...)
  2026-03-25  1:48 ` [PATCH V2 09/17] platform/x86/intel/pmc/ssram: Rename probe and PCI ID table for consistency David E. Box
@ 2026-03-25  1:48 ` David E. Box
  2026-04-07 13:08   ` Ilpo Järvinen
  2026-03-25  1:48 ` [PATCH V2 11/17] platform/x86/intel/pmc/ssram: Refactor DEVID/PWRMBASE extraction into helper David E. Box
                   ` (6 subsequent siblings)
  16 siblings, 1 reply; 27+ messages in thread
From: David E. Box @ 2026-03-25  1:48 UTC (permalink / raw)
  To: irenic.rajneesh, ilpo.jarvinen, srinivas.pandruvada, xi.pardee,
	david.e.box
  Cc: hansg, linux-kernel, platform-driver-x86

From: Xi Pardee <xi.pardee@linux.intel.com>

Switch pmc_ssram_telems from a devm-allocated pointer to a fixed-size
static array, eliminating per-probe allocation overhead and simplifying
lifetime management.

Correspondingly simplify pmc_ssram_telemetry_get_pmc_info() validation to
check devid availability and tighten input bounds checking. Drop
null-pointer checks now that the storage is static.

Signed-off-by: Xi Pardee <xi.pardee@linux.intel.com>
Signed-off-by: David E. Box <david.e.box@linux.intel.com>
---

V2 changes:
- Replaced hardcoded array size [3] with MAX_NUM_PMC constant

 drivers/platform/x86/intel/pmc/ssram_telemetry.c | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/drivers/platform/x86/intel/pmc/ssram_telemetry.c b/drivers/platform/x86/intel/pmc/ssram_telemetry.c
index 1deb4d71da3f..4bfe60ee55ca 100644
--- a/drivers/platform/x86/intel/pmc/ssram_telemetry.c
+++ b/drivers/platform/x86/intel/pmc/ssram_telemetry.c
@@ -24,7 +24,7 @@
 
 DEFINE_FREE(pmc_ssram_telemetry_iounmap, void __iomem *, if (_T) iounmap(_T))
 
-static struct pmc_ssram_telemetry *pmc_ssram_telems;
+static struct pmc_ssram_telemetry pmc_ssram_telems[MAX_NUM_PMC];
 static bool device_probed;
 
 static int
@@ -140,7 +140,7 @@ int pmc_ssram_telemetry_get_pmc_info(unsigned int pmc_idx,
 	if (pmc_idx >= MAX_NUM_PMC)
 		return -EINVAL;
 
-	if (!pmc_ssram_telems || !pmc_ssram_telems[pmc_idx].devid)
+	if (!pmc_ssram_telems[pmc_idx].devid)
 		return -ENODEV;
 
 	pmc_ssram_telemetry->devid = pmc_ssram_telems[pmc_idx].devid;
@@ -153,12 +153,6 @@ static int pmc_ssram_telemetry_probe(struct pci_dev *pcidev, const struct pci_de
 {
 	int ret;
 
-	pmc_ssram_telems = devm_kzalloc(&pcidev->dev, sizeof(*pmc_ssram_telems) * MAX_NUM_PMC,
-					GFP_KERNEL);
-	if (!pmc_ssram_telems) {
-		ret = -ENOMEM;
-		goto probe_finish;
-	}
 
 	ret = pcim_enable_device(pcidev);
 	if (ret) {
-- 
2.43.0


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

* [PATCH V2 11/17] platform/x86/intel/pmc/ssram: Refactor DEVID/PWRMBASE extraction into helper
  2026-03-25  1:48 [PATCH V2 00/17] Add ACPI-based PMT discovery support for Intel PMC David E. Box
                   ` (9 preceding siblings ...)
  2026-03-25  1:48 ` [PATCH V2 10/17] platform/x86/intel/pmc/ssram: Use fixed-size static pmc array David E. Box
@ 2026-03-25  1:48 ` David E. Box
  2026-04-07 13:18   ` Ilpo Järvinen
  2026-03-25  1:48 ` [PATCH V2 12/17] platform/x86/intel/pmc/ssram: Add PCI platform data David E. Box
                   ` (5 subsequent siblings)
  16 siblings, 1 reply; 27+ messages in thread
From: David E. Box @ 2026-03-25  1:48 UTC (permalink / raw)
  To: irenic.rajneesh, ilpo.jarvinen, srinivas.pandruvada, xi.pardee,
	david.e.box
  Cc: hansg, linux-kernel, platform-driver-x86

Move DEVID/PWRMBASE extraction into pmc_ssram_get_devid_pwrmbase().

This is a preparatory refactor to place functionality in a common helper
for reuse by a subsequent patch. Additionally add missing bits.h
include and define SSRAM_BASE_ADDR_MASK for the address extraction mask.

Signed-off-by: David E. Box <david.e.box@linux.intel.com>
---

V2 changes:
- Added missing <linux/bits.h> include for GENMASK_ULL() used in get_base()
- Defined SSRAM_BASE_ADDR_MASK macro to replace magic mask constant
  GENMASK_ULL(63, 3)

 .../platform/x86/intel/pmc/ssram_telemetry.c  | 33 ++++++++++++-------
 1 file changed, 21 insertions(+), 12 deletions(-)

diff --git a/drivers/platform/x86/intel/pmc/ssram_telemetry.c b/drivers/platform/x86/intel/pmc/ssram_telemetry.c
index 4bfe60ee55ca..779e84c724ac 100644
--- a/drivers/platform/x86/intel/pmc/ssram_telemetry.c
+++ b/drivers/platform/x86/intel/pmc/ssram_telemetry.c
@@ -5,6 +5,7 @@
  * Copyright (c) 2023, Intel Corporation.
  */
 
+#include <linux/bits.h>
 #include <linux/cleanup.h>
 #include <linux/intel_vsec.h>
 #include <linux/pci.h>
@@ -21,12 +22,30 @@
 #define SSRAM_PCH_OFFSET	0x60
 #define SSRAM_IOE_OFFSET	0x68
 #define SSRAM_DEVID_OFFSET	0x70
+#define SSRAM_BASE_ADDR_MASK	GENMASK_ULL(63, 3)
 
 DEFINE_FREE(pmc_ssram_telemetry_iounmap, void __iomem *, if (_T) iounmap(_T))
 
 static struct pmc_ssram_telemetry pmc_ssram_telems[MAX_NUM_PMC];
 static bool device_probed;
 
+static inline u64 get_base(void __iomem *addr, u32 offset)
+{
+	return lo_hi_readq(addr + offset) & SSRAM_BASE_ADDR_MASK;
+}
+
+static void pmc_ssram_get_devid_pwrmbase(void __iomem *ssram, unsigned int pmc_idx)
+{
+	u64 pwrm_base;
+	u16 devid;
+
+	pwrm_base = get_base(ssram, SSRAM_PWRM_OFFSET);
+	devid = readw(ssram + SSRAM_DEVID_OFFSET);
+
+	pmc_ssram_telems[pmc_idx].devid = devid;
+	pmc_ssram_telems[pmc_idx].base_addr = pwrm_base;
+}
+
 static int
 pmc_ssram_telemetry_add_pmt(struct pci_dev *pcidev, u64 ssram_base, void __iomem *ssram)
 {
@@ -63,18 +82,12 @@ pmc_ssram_telemetry_add_pmt(struct pci_dev *pcidev, u64 ssram_base, void __iomem
 	return intel_vsec_register(&pcidev->dev, &info);
 }
 
-static inline u64 get_base(void __iomem *addr, u32 offset)
-{
-	return lo_hi_readq(addr + offset) & GENMASK_ULL(63, 3);
-}
-
 static int
 pmc_ssram_telemetry_get_pmc(struct pci_dev *pcidev, unsigned int pmc_idx, u32 offset)
 {
 	void __iomem __free(pmc_ssram_telemetry_iounmap) *tmp_ssram = NULL;
 	void __iomem __free(pmc_ssram_telemetry_iounmap) *ssram = NULL;
-	u64 ssram_base, pwrm_base;
-	u16 devid;
+	u64 ssram_base;
 
 	ssram_base = pci_resource_start(pcidev, 0);
 	tmp_ssram = ioremap(ssram_base, SSRAM_HDR_SIZE);
@@ -99,11 +112,7 @@ pmc_ssram_telemetry_get_pmc(struct pci_dev *pcidev, unsigned int pmc_idx, u32 of
 		ssram = no_free_ptr(tmp_ssram);
 	}
 
-	pwrm_base = get_base(ssram, SSRAM_PWRM_OFFSET);
-	devid = readw(ssram + SSRAM_DEVID_OFFSET);
-
-	pmc_ssram_telems[pmc_idx].devid = devid;
-	pmc_ssram_telems[pmc_idx].base_addr = pwrm_base;
+	pmc_ssram_get_devid_pwrmbase(ssram, pmc_idx);
 
 	/* Find and register and PMC telemetry entries */
 	return pmc_ssram_telemetry_add_pmt(pcidev, ssram_base, ssram);
-- 
2.43.0


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

* [PATCH V2 12/17] platform/x86/intel/pmc/ssram: Add PCI platform data
  2026-03-25  1:48 [PATCH V2 00/17] Add ACPI-based PMT discovery support for Intel PMC David E. Box
                   ` (10 preceding siblings ...)
  2026-03-25  1:48 ` [PATCH V2 11/17] platform/x86/intel/pmc/ssram: Refactor DEVID/PWRMBASE extraction into helper David E. Box
@ 2026-03-25  1:48 ` David E. Box
  2026-03-25  1:48 ` [PATCH V2 13/17] platform/x86/intel/pmc/ssram: Refactor memory barrier for reentrant probe David E. Box
                   ` (4 subsequent siblings)
  16 siblings, 0 replies; 27+ messages in thread
From: David E. Box @ 2026-03-25  1:48 UTC (permalink / raw)
  To: irenic.rajneesh, ilpo.jarvinen, srinivas.pandruvada, xi.pardee,
	david.e.box
  Cc: hansg, linux-kernel, platform-driver-x86

Add per-device platform data for SSRAM telemetry PCI IDs and route probe
through a method selector driven by id->driver_data.

This is a preparatory refactor for follow-on discovery methods while
preserving current behavior: all supported IDs continue to use the PCI
initialization path.
Signed-off-by: David E. Box <david.e.box@linux.intel.com>
---

V2 changes:
- Added missing <linux/device.h> include for dev_dbg() usage in probe

 .../platform/x86/intel/pmc/ssram_telemetry.c  | 70 +++++++++++++++----
 1 file changed, 56 insertions(+), 14 deletions(-)

diff --git a/drivers/platform/x86/intel/pmc/ssram_telemetry.c b/drivers/platform/x86/intel/pmc/ssram_telemetry.c
index 779e84c724ac..6917a10cbc80 100644
--- a/drivers/platform/x86/intel/pmc/ssram_telemetry.c
+++ b/drivers/platform/x86/intel/pmc/ssram_telemetry.c
@@ -7,6 +7,7 @@
 
 #include <linux/bits.h>
 #include <linux/cleanup.h>
+#include <linux/device.h>
 #include <linux/intel_vsec.h>
 #include <linux/pci.h>
 #include <linux/types.h>
@@ -26,6 +27,18 @@
 
 DEFINE_FREE(pmc_ssram_telemetry_iounmap, void __iomem *, if (_T) iounmap(_T))
 
+enum resource_method {
+	RES_METHOD_PCI,
+};
+
+struct ssram_type {
+	enum resource_method method;
+};
+
+static const struct ssram_type pci_main = {
+	.method = RES_METHOD_PCI,
+};
+
 static struct pmc_ssram_telemetry pmc_ssram_telems[MAX_NUM_PMC];
 static bool device_probed;
 
@@ -83,7 +96,7 @@ pmc_ssram_telemetry_add_pmt(struct pci_dev *pcidev, u64 ssram_base, void __iomem
 }
 
 static int
-pmc_ssram_telemetry_get_pmc(struct pci_dev *pcidev, unsigned int pmc_idx, u32 offset)
+pmc_ssram_telemetry_get_pmc_pci(struct pci_dev *pcidev, unsigned int pmc_idx, u32 offset)
 {
 	void __iomem __free(pmc_ssram_telemetry_iounmap) *tmp_ssram = NULL;
 	void __iomem __free(pmc_ssram_telemetry_iounmap) *ssram = NULL;
@@ -118,6 +131,20 @@ pmc_ssram_telemetry_get_pmc(struct pci_dev *pcidev, unsigned int pmc_idx, u32 of
 	return pmc_ssram_telemetry_add_pmt(pcidev, ssram_base, ssram);
 }
 
+static int pmc_ssram_telemetry_pci_init(struct pci_dev *pcidev)
+{
+	int ret;
+
+	ret = pmc_ssram_telemetry_get_pmc_pci(pcidev, PMC_IDX_MAIN, 0);
+	if (ret)
+		return ret;
+
+	pmc_ssram_telemetry_get_pmc_pci(pcidev, PMC_IDX_IOE, SSRAM_IOE_OFFSET);
+	pmc_ssram_telemetry_get_pmc_pci(pcidev, PMC_IDX_PCH, SSRAM_PCH_OFFSET);
+
+	return ret;
+}
+
 /**
  * pmc_ssram_telemetry_get_pmc_info() - Get a PMC devid and base_addr information
  * @pmc_idx:               Index of the PMC
@@ -160,8 +187,18 @@ EXPORT_SYMBOL_GPL(pmc_ssram_telemetry_get_pmc_info);
 
 static int pmc_ssram_telemetry_probe(struct pci_dev *pcidev, const struct pci_device_id *id)
 {
+	const struct ssram_type *ssram_type;
+	enum resource_method method;
 	int ret;
 
+	ssram_type = (const struct ssram_type *)id->driver_data;
+	if (!ssram_type) {
+		dev_dbg(&pcidev->dev, "missing driver data\n");
+		ret = -EINVAL;
+		goto probe_finish;
+	}
+
+	method = ssram_type->method;
 
 	ret = pcim_enable_device(pcidev);
 	if (ret) {
@@ -169,12 +206,10 @@ static int pmc_ssram_telemetry_probe(struct pci_dev *pcidev, const struct pci_de
 		goto probe_finish;
 	}
 
-	ret = pmc_ssram_telemetry_get_pmc(pcidev, PMC_IDX_MAIN, 0);
-	if (ret)
-		goto probe_finish;
-
-	pmc_ssram_telemetry_get_pmc(pcidev, PMC_IDX_IOE, SSRAM_IOE_OFFSET);
-	pmc_ssram_telemetry_get_pmc(pcidev, PMC_IDX_PCH, SSRAM_PCH_OFFSET);
+	if (method == RES_METHOD_PCI)
+		ret = pmc_ssram_telemetry_pci_init(pcidev);
+	else
+		ret = -EINVAL;
 
 probe_finish:
 	/*
@@ -187,13 +222,20 @@ static int pmc_ssram_telemetry_probe(struct pci_dev *pcidev, const struct pci_de
 }
 
 static const struct pci_device_id pmc_ssram_telemetry_pci_ids[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PMC_DEVID_MTL_SOCM) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PMC_DEVID_ARL_SOCS) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PMC_DEVID_ARL_SOCM) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PMC_DEVID_LNL_SOCM) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PMC_DEVID_PTL_PCDH) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PMC_DEVID_PTL_PCDP) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PMC_DEVID_WCL_PCDN) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PMC_DEVID_MTL_SOCM),
+		.driver_data = (kernel_ulong_t)&pci_main },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PMC_DEVID_ARL_SOCS),
+		.driver_data = (kernel_ulong_t)&pci_main },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PMC_DEVID_ARL_SOCM),
+		.driver_data = (kernel_ulong_t)&pci_main },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PMC_DEVID_LNL_SOCM),
+		.driver_data = (kernel_ulong_t)&pci_main },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PMC_DEVID_PTL_PCDH),
+		.driver_data = (kernel_ulong_t)&pci_main },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PMC_DEVID_PTL_PCDP),
+		.driver_data = (kernel_ulong_t)&pci_main },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PMC_DEVID_WCL_PCDN),
+		.driver_data = (kernel_ulong_t)&pci_main },
 	{ }
 };
 MODULE_DEVICE_TABLE(pci, pmc_ssram_telemetry_pci_ids);
-- 
2.43.0


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

* [PATCH V2 13/17] platform/x86/intel/pmc/ssram: Refactor memory barrier for reentrant probe
  2026-03-25  1:48 [PATCH V2 00/17] Add ACPI-based PMT discovery support for Intel PMC David E. Box
                   ` (11 preceding siblings ...)
  2026-03-25  1:48 ` [PATCH V2 12/17] platform/x86/intel/pmc/ssram: Add PCI platform data David E. Box
@ 2026-03-25  1:48 ` David E. Box
  2026-03-25  1:48 ` [PATCH V2 14/17] platform/x86/intel/pmc/ssram_telemetry: Fix cleanup pattern for __free() variables David E. Box
                   ` (3 subsequent siblings)
  16 siblings, 0 replies; 27+ messages in thread
From: David E. Box @ 2026-03-25  1:48 UTC (permalink / raw)
  To: irenic.rajneesh, ilpo.jarvinen, srinivas.pandruvada, xi.pardee,
	david.e.box
  Cc: hansg, linux-kernel, platform-driver-x86

From: Xi Pardee <xi.pardee@linux.intel.com>

Previously, a single global 'device_probed' flag with memory barriers was
used to prevent callers from reading PMC info before probe completion.  The
write barrier in probe ensured all data, devid and base_addr, was visible
before signaling completion, and the read barrier in callers ensured they
checked the flag before reading data.

A following commit will make probe reentrant, requiring that a different
synchronization flag be used since a single global flag cannot coordinate
multiple concurrent probes.

Switch to per-index devid publication. Each probe instance writes base_addr
first, then a write barrier ensures visibility before devid is written as
the completion signal. Callers check devid first, then use a read barrier
before reading base_addr. This per-index approach allows multiple probes
to work independently while maintaining the same memory ordering guarantees.

Signed-off-by: Xi Pardee <xi.pardee@linux.intel.com>
Signed-off-by: David E. Box <david.e.box@linux.intel.com>
---

V2 changes:
- Expanded commit message to explain synchronization rationale
- Remove unused probe_finish label associated with the old global flag

 .../platform/x86/intel/pmc/ssram_telemetry.c  | 40 ++++++++-----------
 1 file changed, 16 insertions(+), 24 deletions(-)

diff --git a/drivers/platform/x86/intel/pmc/ssram_telemetry.c b/drivers/platform/x86/intel/pmc/ssram_telemetry.c
index 6917a10cbc80..b329e0c0080b 100644
--- a/drivers/platform/x86/intel/pmc/ssram_telemetry.c
+++ b/drivers/platform/x86/intel/pmc/ssram_telemetry.c
@@ -40,7 +40,6 @@ static const struct ssram_type pci_main = {
 };
 
 static struct pmc_ssram_telemetry pmc_ssram_telems[MAX_NUM_PMC];
-static bool device_probed;
 
 static inline u64 get_base(void __iomem *addr, u32 offset)
 {
@@ -55,8 +54,13 @@ static void pmc_ssram_get_devid_pwrmbase(void __iomem *ssram, unsigned int pmc_i
 	pwrm_base = get_base(ssram, SSRAM_PWRM_OFFSET);
 	devid = readw(ssram + SSRAM_DEVID_OFFSET);
 
-	pmc_ssram_telems[pmc_idx].devid = devid;
 	pmc_ssram_telems[pmc_idx].base_addr = pwrm_base;
+	/*
+	 * Memory barrier is used to ensure the correct write order between base_addr
+	 * and devid.
+	 */
+	smp_wmb();
+	pmc_ssram_telems[pmc_idx].devid = devid;
 }
 
 static int
@@ -154,32 +158,28 @@ static int pmc_ssram_telemetry_pci_init(struct pci_dev *pcidev)
  * * 0           - Success
  * * -EAGAIN     - Probe function has not finished yet. Try again.
  * * -EINVAL     - Invalid pmc_idx
- * * -ENODEV     - PMC device is not available
  */
 int pmc_ssram_telemetry_get_pmc_info(unsigned int pmc_idx,
 				     struct pmc_ssram_telemetry *pmc_ssram_telemetry)
 {
+	if (pmc_idx >= MAX_NUM_PMC)
+		return -EINVAL;
+
 	/*
 	 * PMCs are discovered in probe function. If this function is called before
-	 * probe function complete, the result would be invalid. Use device_probed
-	 * variable to avoid this case. Return -EAGAIN to inform the consumer to call
+	 * probe function complete, the result would be invalid. Use devid to avoid
+	 * this case. Return -EAGAIN to inform the consumer to call
 	 * again later.
 	 */
-	if (!device_probed)
+	if (!pmc_ssram_telems[pmc_idx].devid)
 		return -EAGAIN;
 
+	pmc_ssram_telemetry->devid = pmc_ssram_telems[pmc_idx].devid;
 	/*
 	 * Memory barrier is used to ensure the correct read order between
-	 * device_probed variable and PMC info.
+	 * devid variable and base_addr.
 	 */
 	smp_rmb();
-	if (pmc_idx >= MAX_NUM_PMC)
-		return -EINVAL;
-
-	if (!pmc_ssram_telems[pmc_idx].devid)
-		return -ENODEV;
-
-	pmc_ssram_telemetry->devid = pmc_ssram_telems[pmc_idx].devid;
 	pmc_ssram_telemetry->base_addr = pmc_ssram_telems[pmc_idx].base_addr;
 	return 0;
 }
@@ -194,8 +194,7 @@ static int pmc_ssram_telemetry_probe(struct pci_dev *pcidev, const struct pci_de
 	ssram_type = (const struct ssram_type *)id->driver_data;
 	if (!ssram_type) {
 		dev_dbg(&pcidev->dev, "missing driver data\n");
-		ret = -EINVAL;
-		goto probe_finish;
+		return -EINVAL;
 	}
 
 	method = ssram_type->method;
@@ -203,7 +202,7 @@ static int pmc_ssram_telemetry_probe(struct pci_dev *pcidev, const struct pci_de
 	ret = pcim_enable_device(pcidev);
 	if (ret) {
 		dev_dbg(&pcidev->dev, "failed to enable PMC SSRAM device\n");
-		goto probe_finish;
+		return ret;
 	}
 
 	if (method == RES_METHOD_PCI)
@@ -211,13 +210,6 @@ static int pmc_ssram_telemetry_probe(struct pci_dev *pcidev, const struct pci_de
 	else
 		ret = -EINVAL;
 
-probe_finish:
-	/*
-	 * Memory barrier is used to ensure the correct write order between PMC info
-	 * and device_probed variable.
-	 */
-	smp_wmb();
-	device_probed = true;
 	return ret;
 }
 
-- 
2.43.0


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

* [PATCH V2 14/17] platform/x86/intel/pmc/ssram_telemetry: Fix cleanup pattern for __free() variables
  2026-03-25  1:48 [PATCH V2 00/17] Add ACPI-based PMT discovery support for Intel PMC David E. Box
                   ` (12 preceding siblings ...)
  2026-03-25  1:48 ` [PATCH V2 13/17] platform/x86/intel/pmc/ssram: Refactor memory barrier for reentrant probe David E. Box
@ 2026-03-25  1:48 ` David E. Box
  2026-04-07 13:33   ` Ilpo Järvinen
  2026-03-25  1:48 ` [PATCH V2 15/17] platform/x86/intel/pmc/ssram: Add ACPI discovery scaffolding David E. Box
                   ` (2 subsequent siblings)
  16 siblings, 1 reply; 27+ messages in thread
From: David E. Box @ 2026-03-25  1:48 UTC (permalink / raw)
  To: irenic.rajneesh, ilpo.jarvinen, srinivas.pandruvada, xi.pardee,
	david.e.box
  Cc: hansg, linux-kernel, platform-driver-x86

Fix improper cleanup.h usage where __free() variables were initialized to
NULL and then assigned later. Move ssram variable declarations into the
if/else branches where they're actually assigned to follow the safer
pattern recommended in cleanup.h.  This change requires also moving the
pmc_ssram_get_devid_pwrmbase() and add_pmt calls into both if/else branches
to keep operations within the scope of the local ssram variables.

Signed-off-by: David E. Box <david.e.box@linux.intel.com>
---

V2 changes:
- New patch addressing Ilpo's review of cleanup.h patterns

 .../platform/x86/intel/pmc/ssram_telemetry.c  | 25 +++++++++++--------
 1 file changed, 15 insertions(+), 10 deletions(-)

diff --git a/drivers/platform/x86/intel/pmc/ssram_telemetry.c b/drivers/platform/x86/intel/pmc/ssram_telemetry.c
index b329e0c0080b..b1ba17f18ea5 100644
--- a/drivers/platform/x86/intel/pmc/ssram_telemetry.c
+++ b/drivers/platform/x86/intel/pmc/ssram_telemetry.c
@@ -102,12 +102,11 @@ pmc_ssram_telemetry_add_pmt(struct pci_dev *pcidev, u64 ssram_base, void __iomem
 static int
 pmc_ssram_telemetry_get_pmc_pci(struct pci_dev *pcidev, unsigned int pmc_idx, u32 offset)
 {
-	void __iomem __free(pmc_ssram_telemetry_iounmap) *tmp_ssram = NULL;
-	void __iomem __free(pmc_ssram_telemetry_iounmap) *ssram = NULL;
 	u64 ssram_base;
 
 	ssram_base = pci_resource_start(pcidev, 0);
-	tmp_ssram = ioremap(ssram_base, SSRAM_HDR_SIZE);
+	void __iomem __free(pmc_ssram_telemetry_iounmap) *tmp_ssram =
+		ioremap(ssram_base, SSRAM_HDR_SIZE);
 	if (!tmp_ssram)
 		return -ENOMEM;
 
@@ -121,18 +120,24 @@ pmc_ssram_telemetry_get_pmc_pci(struct pci_dev *pcidev, unsigned int pmc_idx, u3
 		if (!ssram_base)
 			return 0;
 
-		ssram = ioremap(ssram_base, SSRAM_HDR_SIZE);
+		void __iomem __free(pmc_ssram_telemetry_iounmap) *ssram =
+			ioremap(ssram_base, SSRAM_HDR_SIZE);
 		if (!ssram)
 			return -ENOMEM;
 
+		pmc_ssram_get_devid_pwrmbase(ssram, pmc_idx);
+
+		/* Find and register and PMC telemetry entries */
+		return pmc_ssram_telemetry_add_pmt(pcidev, ssram_base, ssram);
 	} else {
-		ssram = no_free_ptr(tmp_ssram);
+		void __iomem __free(pmc_ssram_telemetry_iounmap) *ssram =
+			no_free_ptr(tmp_ssram);
+
+		pmc_ssram_get_devid_pwrmbase(ssram, pmc_idx);
+
+		/* Find and register and PMC telemetry entries */
+		return pmc_ssram_telemetry_add_pmt(pcidev, ssram_base, ssram);
 	}
-
-	pmc_ssram_get_devid_pwrmbase(ssram, pmc_idx);
-
-	/* Find and register and PMC telemetry entries */
-	return pmc_ssram_telemetry_add_pmt(pcidev, ssram_base, ssram);
 }
 
 static int pmc_ssram_telemetry_pci_init(struct pci_dev *pcidev)
-- 
2.43.0


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

* [PATCH V2 15/17] platform/x86/intel/pmc/ssram: Add ACPI discovery scaffolding
  2026-03-25  1:48 [PATCH V2 00/17] Add ACPI-based PMT discovery support for Intel PMC David E. Box
                   ` (13 preceding siblings ...)
  2026-03-25  1:48 ` [PATCH V2 14/17] platform/x86/intel/pmc/ssram_telemetry: Fix cleanup pattern for __free() variables David E. Box
@ 2026-03-25  1:48 ` David E. Box
  2026-03-25  1:48 ` [PATCH V2 16/17] platform/x86/intel/pmc/ssram: Make PMT registration optional David E. Box
  2026-03-25  1:48 ` [PATCH V2 17/17] platform/x86/intel/pmc: Add NVL PCI IDs for SSRAM telemetry discovery David E. Box
  16 siblings, 0 replies; 27+ messages in thread
From: David E. Box @ 2026-03-25  1:48 UTC (permalink / raw)
  To: irenic.rajneesh, ilpo.jarvinen, srinivas.pandruvada, xi.pardee,
	david.e.box
  Cc: hansg, linux-kernel, platform-driver-x86

Prepare the SSRAM telemetry driver for ACPI-based discovery by adding the
common initialization path and selection framework needed for both PCI and
ACPI resource discovery.

At this stage, existing supported devices continue to use the PCI path.
This change lays the groundwork for follow-on patches that wire platform
IDs to the ACPI policy path.

Signed-off-by: David E. Box <david.e.box@linux.intel.com>
Signed-off-by: Xi Pardee <xi.pardee@linux.intel.com>
---

V2 changes:
- Fixed cleanup patterns using __free() attributes
- Addressed Ilpo's recommendations for safer cleanup.h patterns

 .../platform/x86/intel/pmc/ssram_telemetry.c  | 70 +++++++++++++++++++
 1 file changed, 70 insertions(+)

diff --git a/drivers/platform/x86/intel/pmc/ssram_telemetry.c b/drivers/platform/x86/intel/pmc/ssram_telemetry.c
index b1ba17f18ea5..543f7d7c5049 100644
--- a/drivers/platform/x86/intel/pmc/ssram_telemetry.c
+++ b/drivers/platform/x86/intel/pmc/ssram_telemetry.c
@@ -5,6 +5,7 @@
  * Copyright (c) 2023, Intel Corporation.
  */
 
+#include <linux/acpi.h>
 #include <linux/bits.h>
 #include <linux/cleanup.h>
 #include <linux/device.h>
@@ -29,14 +30,17 @@ DEFINE_FREE(pmc_ssram_telemetry_iounmap, void __iomem *, if (_T) iounmap(_T))
 
 enum resource_method {
 	RES_METHOD_PCI,
+	RES_METHOD_ACPI,
 };
 
 struct ssram_type {
 	enum resource_method method;
+	enum pmc_index p_index;
 };
 
 static const struct ssram_type pci_main = {
 	.method = RES_METHOD_PCI,
+	.p_index = PMC_IDX_MAIN,
 };
 
 static struct pmc_ssram_telemetry pmc_ssram_telems[MAX_NUM_PMC];
@@ -154,6 +158,67 @@ static int pmc_ssram_telemetry_pci_init(struct pci_dev *pcidev)
 	return ret;
 }
 
+static int pmc_ssram_telemetry_get_pmc_acpi(struct pci_dev *pcidev,  unsigned int pmc_idx)
+{
+	u64 ssram_base;
+
+	ssram_base = pci_resource_start(pcidev, 0);
+	if (!ssram_base)
+		return -ENODEV;
+
+	void __iomem __free(pmc_ssram_telemetry_iounmap) *ssram =
+		ioremap(ssram_base, SSRAM_HDR_SIZE);
+	if (!ssram)
+		return -ENOMEM;
+
+	pmc_ssram_get_devid_pwrmbase(ssram, pmc_idx);
+
+	return 0;
+}
+
+static int pmc_ssram_telemetry_acpi_init(struct pci_dev *pcidev,
+					 enum pmc_index index)
+{
+	struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
+	acpi_handle handle = ACPI_HANDLE(&pcidev->dev);
+	struct intel_vsec_header header;
+	struct intel_vsec_header *headers[2] = { &header, NULL };
+	struct intel_vsec_platform_info info = { };
+	void *dsd_buf __free(pmc_acpi_free) = buf.pointer;
+	union acpi_object *dsd;
+	acpi_status status;
+	int ret;
+
+	if (!handle)
+		return -ENODEV;
+
+	status = acpi_evaluate_object(handle, "_DSD", NULL, &buf);
+	if (ACPI_FAILURE(status))
+		return -ENODEV;
+
+	dsd = pmc_find_telem_guid(buf.pointer);
+	if (!dsd)
+		return -ENODEV;
+
+	u32 (*acpi_disc)[4] __free(kfree) = pmc_parse_telem_dsd(dsd, &header);
+	if (IS_ERR(acpi_disc))
+		return PTR_ERR(acpi_disc);
+
+	info.headers = headers;
+	info.caps = VSEC_CAP_TELEMETRY;
+	info.acpi_disc = acpi_disc;
+	info.src = INTEL_VSEC_DISC_ACPI;
+
+	/* This is an ACPI companion device. PCI BAR will be used for base addr. */
+	info.base_addr = 0;
+
+	ret = intel_vsec_register(&pcidev->dev, &info);
+	if (ret)
+		return ret;
+
+	return pmc_ssram_telemetry_get_pmc_acpi(pcidev, index);
+}
+
 /**
  * pmc_ssram_telemetry_get_pmc_info() - Get a PMC devid and base_addr information
  * @pmc_idx:               Index of the PMC
@@ -194,6 +259,7 @@ static int pmc_ssram_telemetry_probe(struct pci_dev *pcidev, const struct pci_de
 {
 	const struct ssram_type *ssram_type;
 	enum resource_method method;
+	enum pmc_index index;
 	int ret;
 
 	ssram_type = (const struct ssram_type *)id->driver_data;
@@ -203,6 +269,7 @@ static int pmc_ssram_telemetry_probe(struct pci_dev *pcidev, const struct pci_de
 	}
 
 	method = ssram_type->method;
+	index = ssram_type->p_index;
 
 	ret = pcim_enable_device(pcidev);
 	if (ret) {
@@ -212,6 +279,8 @@ static int pmc_ssram_telemetry_probe(struct pci_dev *pcidev, const struct pci_de
 
 	if (method == RES_METHOD_PCI)
 		ret = pmc_ssram_telemetry_pci_init(pcidev);
+	else if (method == RES_METHOD_ACPI)
+		ret = pmc_ssram_telemetry_acpi_init(pcidev, index);
 	else
 		ret = -EINVAL;
 
@@ -244,6 +313,7 @@ static struct pci_driver pmc_ssram_telemetry_driver = {
 };
 module_pci_driver(pmc_ssram_telemetry_driver);
 
+MODULE_IMPORT_NS("INTEL_PMC_CORE");
 MODULE_IMPORT_NS("INTEL_VSEC");
 MODULE_AUTHOR("Xi Pardee <xi.pardee@intel.com>");
 MODULE_DESCRIPTION("Intel PMC SSRAM Telemetry driver");
-- 
2.43.0


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

* [PATCH V2 16/17] platform/x86/intel/pmc/ssram: Make PMT registration optional
  2026-03-25  1:48 [PATCH V2 00/17] Add ACPI-based PMT discovery support for Intel PMC David E. Box
                   ` (14 preceding siblings ...)
  2026-03-25  1:48 ` [PATCH V2 15/17] platform/x86/intel/pmc/ssram: Add ACPI discovery scaffolding David E. Box
@ 2026-03-25  1:48 ` David E. Box
  2026-03-25  1:48 ` [PATCH V2 17/17] platform/x86/intel/pmc: Add NVL PCI IDs for SSRAM telemetry discovery David E. Box
  16 siblings, 0 replies; 27+ messages in thread
From: David E. Box @ 2026-03-25  1:48 UTC (permalink / raw)
  To: irenic.rajneesh, ilpo.jarvinen, srinivas.pandruvada, xi.pardee,
	david.e.box
  Cc: hansg, linux-kernel, platform-driver-x86

The SSRAM telemetry driver extracts essential PMC device ID and power
management base address information that intel_pmc_core depends on for core
functionality. If PMT registration failure prevents this critical data from
being available, intel_pmc_core operation would break entirely. Therefore,
PMT registration failures must not block access to this data.

Change the behavior to log a warning when PMT registration fails but
continue with successful driver initialization, ensuring the primary
telemetry data remains accessible to dependent drivers.

Signed-off-by: David E. Box <david.e.box@linux.intel.com>
---

V2 changes:
- Update commit message for clarity
- Also apply the PCI telemetry path

 drivers/platform/x86/intel/pmc/ssram_telemetry.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/platform/x86/intel/pmc/ssram_telemetry.c b/drivers/platform/x86/intel/pmc/ssram_telemetry.c
index 543f7d7c5049..74a2f56881c1 100644
--- a/drivers/platform/x86/intel/pmc/ssram_telemetry.c
+++ b/drivers/platform/x86/intel/pmc/ssram_telemetry.c
@@ -107,6 +107,7 @@ static int
 pmc_ssram_telemetry_get_pmc_pci(struct pci_dev *pcidev, unsigned int pmc_idx, u32 offset)
 {
 	u64 ssram_base;
+	int ret;
 
 	ssram_base = pci_resource_start(pcidev, 0);
 	void __iomem __free(pmc_ssram_telemetry_iounmap) *tmp_ssram =
@@ -132,7 +133,9 @@ pmc_ssram_telemetry_get_pmc_pci(struct pci_dev *pcidev, unsigned int pmc_idx, u3
 		pmc_ssram_get_devid_pwrmbase(ssram, pmc_idx);
 
 		/* Find and register and PMC telemetry entries */
-		return pmc_ssram_telemetry_add_pmt(pcidev, ssram_base, ssram);
+		ret = pmc_ssram_telemetry_add_pmt(pcidev, ssram_base, ssram);
+		if (ret)
+			dev_warn(&pcidev->dev, "could not register PMT\n");
 	} else {
 		void __iomem __free(pmc_ssram_telemetry_iounmap) *ssram =
 			no_free_ptr(tmp_ssram);
@@ -140,8 +143,12 @@ pmc_ssram_telemetry_get_pmc_pci(struct pci_dev *pcidev, unsigned int pmc_idx, u3
 		pmc_ssram_get_devid_pwrmbase(ssram, pmc_idx);
 
 		/* Find and register and PMC telemetry entries */
-		return pmc_ssram_telemetry_add_pmt(pcidev, ssram_base, ssram);
+		ret = pmc_ssram_telemetry_add_pmt(pcidev, ssram_base, ssram);
+		if (ret)
+			dev_warn(&pcidev->dev, "could not register PMT\n");
 	}
+
+	return 0;
 }
 
 static int pmc_ssram_telemetry_pci_init(struct pci_dev *pcidev)
@@ -214,7 +221,7 @@ static int pmc_ssram_telemetry_acpi_init(struct pci_dev *pcidev,
 
 	ret = intel_vsec_register(&pcidev->dev, &info);
 	if (ret)
-		return ret;
+		dev_warn(&pcidev->dev, "could not register PMT\n");
 
 	return pmc_ssram_telemetry_get_pmc_acpi(pcidev, index);
 }
-- 
2.43.0


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

* [PATCH V2 17/17] platform/x86/intel/pmc: Add NVL PCI IDs for SSRAM telemetry discovery
  2026-03-25  1:48 [PATCH V2 00/17] Add ACPI-based PMT discovery support for Intel PMC David E. Box
                   ` (15 preceding siblings ...)
  2026-03-25  1:48 ` [PATCH V2 16/17] platform/x86/intel/pmc/ssram: Make PMT registration optional David E. Box
@ 2026-03-25  1:48 ` David E. Box
  16 siblings, 0 replies; 27+ messages in thread
From: David E. Box @ 2026-03-25  1:48 UTC (permalink / raw)
  To: irenic.rajneesh, ilpo.jarvinen, srinivas.pandruvada, xi.pardee,
	david.e.box
  Cc: hansg, linux-kernel, platform-driver-x86

Add Nova Lake S PMC device IDs to enable binding of the SSRAM telemetry
driver on NVL platforms, and map them to the ACPI-based discovery policy.

Signed-off-by: David E. Box <david.e.box@linux.intel.com>
---

V2 - No changes

 drivers/platform/x86/intel/pmc/core.h            |  5 +++++
 drivers/platform/x86/intel/pmc/ssram_telemetry.c | 16 ++++++++++++++++
 2 files changed, 21 insertions(+)

diff --git a/drivers/platform/x86/intel/pmc/core.h b/drivers/platform/x86/intel/pmc/core.h
index 37ea1caf1817..c4c4a33f2e05 100644
--- a/drivers/platform/x86/intel/pmc/core.h
+++ b/drivers/platform/x86/intel/pmc/core.h
@@ -333,6 +333,11 @@ enum ppfear_regs {
 #define PMC_DEVID_MTL_IOEP	0x7ecf
 #define PMC_DEVID_MTL_IOEM	0x7ebf
 
+/* NVL */
+#define PMC_DEVID_NVL_PCDH	0xd37e
+#define PMC_DEVID_NVL_PCDS	0xd47e
+#define PMC_DEVID_NVL_PCHS	0x6e27
+
 extern const char *pmc_lpm_modes[];
 
 struct pmc_bit_map {
diff --git a/drivers/platform/x86/intel/pmc/ssram_telemetry.c b/drivers/platform/x86/intel/pmc/ssram_telemetry.c
index 74a2f56881c1..848e259a89cf 100644
--- a/drivers/platform/x86/intel/pmc/ssram_telemetry.c
+++ b/drivers/platform/x86/intel/pmc/ssram_telemetry.c
@@ -43,6 +43,16 @@ static const struct ssram_type pci_main = {
 	.p_index = PMC_IDX_MAIN,
 };
 
+static const struct ssram_type acpi_main = {
+	.method = RES_METHOD_ACPI,
+	.p_index = PMC_IDX_MAIN,
+};
+
+static const struct ssram_type acpi_pch = {
+	.method = RES_METHOD_ACPI,
+	.p_index = PMC_IDX_PCH,
+};
+
 static struct pmc_ssram_telemetry pmc_ssram_telems[MAX_NUM_PMC];
 
 static inline u64 get_base(void __iomem *addr, u32 offset)
@@ -309,6 +319,12 @@ static const struct pci_device_id pmc_ssram_telemetry_pci_ids[] = {
 		.driver_data = (kernel_ulong_t)&pci_main },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PMC_DEVID_WCL_PCDN),
 		.driver_data = (kernel_ulong_t)&pci_main },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PMC_DEVID_NVL_PCDH),
+		.driver_data = (kernel_ulong_t)&acpi_main },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PMC_DEVID_NVL_PCDS),
+		.driver_data = (kernel_ulong_t)&acpi_main },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PMC_DEVID_NVL_PCHS),
+		.driver_data = (kernel_ulong_t)&acpi_pch },
 	{ }
 };
 MODULE_DEVICE_TABLE(pci, pmc_ssram_telemetry_pci_ids);
-- 
2.43.0


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

* Re: [PATCH V2 04/17] platform/x86/intel/pmt: Move header decode into common helper
  2026-03-25  1:48 ` [PATCH V2 04/17] platform/x86/intel/pmt: Move header decode into common helper David E. Box
@ 2026-04-07 11:05   ` Ilpo Järvinen
  0 siblings, 0 replies; 27+ messages in thread
From: Ilpo Järvinen @ 2026-04-07 11:05 UTC (permalink / raw)
  To: David E. Box
  Cc: irenic.rajneesh, srinivas.pandruvada, xi.pardee, Hans de Goede,
	LKML, platform-driver-x86

On Tue, 24 Mar 2026, David E. Box wrote:

> Unify PMT discovery table parsing by moving header decode logic into the
> class driver. A new helper, pmt_read_header(), now fills in the standard
> header fields from the discovery table, replacing the per-namespace
> pmt_header_decode callbacks in telemetry and crashlog.
> 
> This centralizes the discovery table bit-field definitions in class.h,
> removes duplicate decode code from telemetry and crashlog, and prepares the
> PMT class for additional discovery sources.
> 
> Signed-off-by: David E. Box <david.e.box@linux.intel.com>
> ---
> 
> V2 changes:
> - Added PMT_GET_SIZE_BYTES(v), addressing Ilpo feedback on macro naming
>   and unit clarity
> - Also in PMT_GET_SIZE_BYTES(v) change ((v) << 2) to ((v) * sizeof(u32))
>   for clarity
> - Removed unused macros from crashlog.c per feedback from Ilpo
> 
>  drivers/platform/x86/intel/pmt/class.c     | 37 +++++++++++++++-------
>  drivers/platform/x86/intel/pmt/class.h     | 15 +++++++--
>  drivers/platform/x86/intel/pmt/crashlog.c  | 23 --------------
>  drivers/platform/x86/intel/pmt/telemetry.c | 26 ---------------
>  4 files changed, 39 insertions(+), 62 deletions(-)
> 
> diff --git a/drivers/platform/x86/intel/pmt/class.c b/drivers/platform/x86/intel/pmt/class.c
> index 9b315334a69b..d652b21261f0 100644
> --- a/drivers/platform/x86/intel/pmt/class.c
> +++ b/drivers/platform/x86/intel/pmt/class.c
> @@ -8,6 +8,7 @@
>   * Author: "Alexander Duyck" <alexander.h.duyck@linux.intel.com>
>   */
>  
> +#include <linux/bitfield.h>
>  #include <linux/kernel.h>
>  #include <linux/log2.h>
>  #include <linux/intel_vsec.h>
> @@ -368,26 +369,40 @@ static int intel_pmt_dev_register(struct intel_pmt_entry *entry,
>  	return ret;
>  }
>  
> -int intel_pmt_dev_create(struct intel_pmt_entry *entry, struct intel_pmt_namespace *ns,
> -			 struct intel_vsec_device *intel_vsec_dev, int idx)
> +static int pmt_read_header(struct intel_vsec_device *ivdev, int idx,
> +			   struct intel_pmt_entry *entry)
>  {
> -	struct device *dev = &intel_vsec_dev->auxdev.dev;
> -	struct resource	*disc_res;
> -	int ret;
> +	struct intel_pmt_header *header = &entry->header;
> +	struct device *dev = &ivdev->auxdev.dev;
> +	u64 headers[2];
>  
> -	disc_res = &intel_vsec_dev->resource[idx];
> -
> -	entry->disc_table = devm_ioremap_resource(dev, disc_res);
> +	entry->disc_table = devm_ioremap_resource(dev, &ivdev->resource[idx]);
>  	if (IS_ERR(entry->disc_table))
>  		return PTR_ERR(entry->disc_table);
>  
> +	memcpy_fromio(headers, entry->disc_table, 2 * sizeof(u64));
> +
> +	header->access_type = FIELD_GET(PMT_ACCESS_TYPE, headers[0]);
> +	header->telem_type = FIELD_GET(PMT_TELEM_TYPE, headers[0]);
> +	header->size = PMT_GET_SIZE_BYTES(headers[0]);

Hi David,

There might be something I'm missing that is not apparent from the code 
alone, but when I look the old code in pmt_crashlog_header_decode(), it 
has this:

#define SIZE_OFFSET            0xC
...
	header->size = GET_SIZE(readl(disc_table + SIZE_OFFSET));

...I can't understand how this transformation is equivalent as it was 
previously read from 0xC which would belong into header[1], right?

I think it warrants an explanation in changelog if it's an intended 
change.

-- 
 i.

> +	header->guid = FIELD_GET(PMT_GUID32, headers[0]);
> +	header->base_offset = FIELD_GET(PMT_BASE_OFFSET, headers[1]);
> +
> +	return 0;
> +}
> +
> +int intel_pmt_dev_create(struct intel_pmt_entry *entry, struct intel_pmt_namespace *ns,
> +			 struct intel_vsec_device *intel_vsec_dev, int idx)
> +{
> +	int ret;
> +
>  	if (ns->pmt_pre_decode) {
>  		ret = ns->pmt_pre_decode(intel_vsec_dev, entry);
>  		if (ret)
>  			return ret;
>  	}
>  
> -	ret = ns->pmt_header_decode(entry, dev);
> +	ret = pmt_read_header(intel_vsec_dev, idx, entry);
>  	if (ret)
>  		return ret;
>  
> @@ -397,11 +412,11 @@ int intel_pmt_dev_create(struct intel_pmt_entry *entry, struct intel_pmt_namespa
>  			return ret;
>  	}
>  
> -	ret = intel_pmt_populate_entry(entry, intel_vsec_dev, disc_res);
> +	ret = intel_pmt_populate_entry(entry, intel_vsec_dev, &intel_vsec_dev->resource[idx]);
>  	if (ret)
>  		return ret;
>  
> -	return intel_pmt_dev_register(entry, ns, dev);
> +	return intel_pmt_dev_register(entry, ns, &intel_vsec_dev->auxdev.dev);
>  }
>  EXPORT_SYMBOL_NS_GPL(intel_pmt_dev_create, "INTEL_PMT");
>  
> diff --git a/drivers/platform/x86/intel/pmt/class.h b/drivers/platform/x86/intel/pmt/class.h
> index 8a0db0ef58c1..96ebb15f0053 100644
> --- a/drivers/platform/x86/intel/pmt/class.h
> +++ b/drivers/platform/x86/intel/pmt/class.h
> @@ -11,6 +11,19 @@
>  
>  #include "telemetry.h"
>  
> +/* PMT Discovery Table DWORD 1 */
> +#define PMT_ACCESS_TYPE		GENMASK_ULL(3, 0)
> +#define PMT_TELEM_TYPE		GENMASK_ULL(7, 4)
> +#define PMT_SIZE		GENMASK_ULL(27, 12)
> +#define PMT_GUID32		GENMASK_ULL(63, 32)
> +
> +/* PMT Discovery Table DWORD 2 */
> +#define PMT_BASE_OFFSET		GENMASK_ULL(31, 0)
> +#define PMT_TELE_ID		GENMASK_ULL(63, 32)
> +
> +/* Convert DWORD size to bytes */
> +#define PMT_GET_SIZE_BYTES(h)	((FIELD_GET(PMT_SIZE, h)) * sizeof(u32))
> +
>  /* PMT access types */
>  #define ACCESS_BARID		2
>  #define ACCESS_LOCAL		3
> @@ -61,8 +74,6 @@ struct intel_pmt_entry {
>  struct intel_pmt_namespace {
>  	const char *name;
>  	struct xarray *xa;
> -	int (*pmt_header_decode)(struct intel_pmt_entry *entry,
> -				 struct device *dev);
>  	int (*pmt_pre_decode)(struct intel_vsec_device *ivdev,
>  			      struct intel_pmt_entry *entry);
>  	int (*pmt_post_decode)(struct intel_vsec_device *ivdev,
> diff --git a/drivers/platform/x86/intel/pmt/crashlog.c b/drivers/platform/x86/intel/pmt/crashlog.c
> index f936daf99e4d..ef1826b15cf4 100644
> --- a/drivers/platform/x86/intel/pmt/crashlog.c
> +++ b/drivers/platform/x86/intel/pmt/crashlog.c
> @@ -26,14 +26,8 @@
>  
>  /* Crashlog Discovery Header */
>  #define CONTROL_OFFSET		0x0
> -#define GUID_OFFSET		0x4
> -#define BASE_OFFSET		0x8
> -#define SIZE_OFFSET		0xC
> -#define GET_ACCESS(v)		((v) & GENMASK(3, 0))
>  #define GET_TYPE(v)		(((v) & GENMASK(7, 4)) >> 4)
>  #define GET_VERSION(v)		(((v) & GENMASK(19, 16)) >> 16)
> -/* size is in bytes */
> -#define GET_SIZE(v)		((v) * sizeof(u32))
>  
>  /*
>   * Type 1 Version 0
> @@ -516,28 +510,11 @@ static int pmt_crashlog_pre_decode(struct intel_vsec_device *ivdev,
>  	return 0;
>  }
>  
> -static int pmt_crashlog_header_decode(struct intel_pmt_entry *entry,
> -				      struct device *dev)
> -{
> -	void __iomem *disc_table = entry->disc_table;
> -	struct intel_pmt_header *header = &entry->header;
> -
> -	header->access_type = GET_ACCESS(readl(disc_table));
> -	header->guid = readl(disc_table + GUID_OFFSET);
> -	header->base_offset = readl(disc_table + BASE_OFFSET);
> -
> -	/* Size is measured in DWORDS, but accessor returns bytes */
> -	header->size = GET_SIZE(readl(disc_table + SIZE_OFFSET));
> -
> -	return 0;
> -}
> -
>  static DEFINE_XARRAY_ALLOC(crashlog_array);
>  static struct intel_pmt_namespace pmt_crashlog_ns = {
>  	.name = "crashlog",
>  	.xa = &crashlog_array,
>  	.pmt_pre_decode = pmt_crashlog_pre_decode,
> -	.pmt_header_decode = pmt_crashlog_header_decode,
>  };
>  
>  /*
> diff --git a/drivers/platform/x86/intel/pmt/telemetry.c b/drivers/platform/x86/intel/pmt/telemetry.c
> index d22f633638be..80773e3c3efa 100644
> --- a/drivers/platform/x86/intel/pmt/telemetry.c
> +++ b/drivers/platform/x86/intel/pmt/telemetry.c
> @@ -27,14 +27,6 @@
>  
>  #include "class.h"
>  
> -#define TELEM_SIZE_OFFSET	0x0
> -#define TELEM_GUID_OFFSET	0x4
> -#define TELEM_BASE_OFFSET	0x8
> -#define TELEM_ACCESS(v)		((v) & GENMASK(3, 0))
> -#define TELEM_TYPE(v)		(((v) & GENMASK(7, 4)) >> 4)
> -/* size is in bytes */
> -#define TELEM_SIZE(v)		(((v) & GENMASK(27, 12)) >> 10)
> -
>  /* Used by client hardware to identify a fixed telemetry entry*/
>  #define TELEM_CLIENT_FIXED_BLOCK_GUID	0x10000000
>  
> @@ -69,23 +61,6 @@ static bool pmt_telem_region_overlaps(struct device *dev, u32 guid, u32 type)
>  	return false;
>  }
>  
> -static int pmt_telem_header_decode(struct intel_pmt_entry *entry,
> -				   struct device *dev)
> -{
> -	void __iomem *disc_table = entry->disc_table;
> -	struct intel_pmt_header *header = &entry->header;
> -
> -	header->access_type = TELEM_ACCESS(readl(disc_table));
> -	header->guid = readl(disc_table + TELEM_GUID_OFFSET);
> -	header->base_offset = readl(disc_table + TELEM_BASE_OFFSET);
> -
> -	/* Size is measured in DWORDS, but accessor returns bytes */
> -	header->size = TELEM_SIZE(readl(disc_table));
> -	header->telem_type = TELEM_TYPE(readl(entry->disc_table));
> -
> -	return 0;
> -}
> -
>  static int pmt_telem_post_decode(struct intel_vsec_device *ivdev,
>  				 struct intel_pmt_entry *entry)
>  {
> @@ -135,7 +110,6 @@ static DEFINE_XARRAY_ALLOC(telem_array);
>  static struct intel_pmt_namespace pmt_telem_ns = {
>  	.name = "telem",
>  	.xa = &telem_array,
> -	.pmt_header_decode = pmt_telem_header_decode,
>  	.pmt_post_decode = pmt_telem_post_decode,
>  	.pmt_add_endpoint = pmt_telem_add_endpoint,
>  };
> 

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

* Re: [PATCH V2 03/17] platform/x86/intel/pmt/telemetry: Move overlap check to post-decode hook
  2026-03-25  1:48 ` [PATCH V2 03/17] platform/x86/intel/pmt/telemetry: Move overlap check to post-decode hook David E. Box
@ 2026-04-07 11:05   ` Ilpo Järvinen
  0 siblings, 0 replies; 27+ messages in thread
From: Ilpo Järvinen @ 2026-04-07 11:05 UTC (permalink / raw)
  To: David E. Box
  Cc: irenic.rajneesh, srinivas.pandruvada, xi.pardee, Hans de Goede,
	LKML, platform-driver-x86

[-- Attachment #1: Type: text/plain, Size: 3333 bytes --]

On Tue, 24 Mar 2026, David E. Box wrote:

> Update the telemetry namespace to use the new PMT class pre/post decode
> interface. The overlap check, which previously occurred during header
> decode, is now performed in the post-decode hook once header fields are
> populated. This preserves existing behavior while reusing the same header
> decode logic across PMT drivers.
> 
> Signed-off-by: David E. Box <david.e.box@linux.intel.com>

For patches #1-#3,

Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>

--
 i.

> ---
> 
> V2 - No changes
> 
>  drivers/platform/x86/intel/pmt/class.h     |  1 +
>  drivers/platform/x86/intel/pmt/telemetry.c | 24 ++++++++++++++--------
>  2 files changed, 16 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/platform/x86/intel/pmt/class.h b/drivers/platform/x86/intel/pmt/class.h
> index ff39014b208c..8a0db0ef58c1 100644
> --- a/drivers/platform/x86/intel/pmt/class.h
> +++ b/drivers/platform/x86/intel/pmt/class.h
> @@ -37,6 +37,7 @@ struct intel_pmt_header {
>  	u32	size;
>  	u32	guid;
>  	u8	access_type;
> +	u8	telem_type;
>  };
>  
>  struct intel_pmt_entry {
> diff --git a/drivers/platform/x86/intel/pmt/telemetry.c b/drivers/platform/x86/intel/pmt/telemetry.c
> index bdc7c24a3678..d22f633638be 100644
> --- a/drivers/platform/x86/intel/pmt/telemetry.c
> +++ b/drivers/platform/x86/intel/pmt/telemetry.c
> @@ -58,14 +58,9 @@ struct pmt_telem_priv {
>  	struct intel_pmt_entry		entry[];
>  };
>  
> -static bool pmt_telem_region_overlaps(struct intel_pmt_entry *entry,
> -				      struct device *dev)
> +static bool pmt_telem_region_overlaps(struct device *dev, u32 guid, u32 type)
>  {
> -	u32 guid = readl(entry->disc_table + TELEM_GUID_OFFSET);
> -
>  	if (intel_pmt_is_early_client_hw(dev)) {
> -		u32 type = TELEM_TYPE(readl(entry->disc_table));
> -
>  		if ((type == TELEM_TYPE_PUNIT_FIXED) ||
>  		    (guid == TELEM_CLIENT_FIXED_BLOCK_GUID))
>  			return true;
> @@ -80,15 +75,25 @@ static int pmt_telem_header_decode(struct intel_pmt_entry *entry,
>  	void __iomem *disc_table = entry->disc_table;
>  	struct intel_pmt_header *header = &entry->header;
>  
> -	if (pmt_telem_region_overlaps(entry, dev))
> -		return 1;
> -
>  	header->access_type = TELEM_ACCESS(readl(disc_table));
>  	header->guid = readl(disc_table + TELEM_GUID_OFFSET);
>  	header->base_offset = readl(disc_table + TELEM_BASE_OFFSET);
>  
>  	/* Size is measured in DWORDS, but accessor returns bytes */
>  	header->size = TELEM_SIZE(readl(disc_table));
> +	header->telem_type = TELEM_TYPE(readl(entry->disc_table));
> +
> +	return 0;
> +}
> +
> +static int pmt_telem_post_decode(struct intel_vsec_device *ivdev,
> +				 struct intel_pmt_entry *entry)
> +{
> +	struct intel_pmt_header *header = &entry->header;
> +	struct device *dev = &ivdev->auxdev.dev;
> +
> +	if (pmt_telem_region_overlaps(dev, header->guid, header->telem_type))
> +		return 1;
>  
>  	/*
>  	 * Some devices may expose non-functioning entries that are
> @@ -131,6 +136,7 @@ static struct intel_pmt_namespace pmt_telem_ns = {
>  	.name = "telem",
>  	.xa = &telem_array,
>  	.pmt_header_decode = pmt_telem_header_decode,
> +	.pmt_post_decode = pmt_telem_post_decode,
>  	.pmt_add_endpoint = pmt_telem_add_endpoint,
>  };
>  
> 

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

* Re: [PATCH V2 05/17] platform/x86/intel/pmt: Pass discovery index instead of resource
  2026-03-25  1:48 ` [PATCH V2 05/17] platform/x86/intel/pmt: Pass discovery index instead of resource David E. Box
@ 2026-04-07 11:07   ` Ilpo Järvinen
  0 siblings, 0 replies; 27+ messages in thread
From: Ilpo Järvinen @ 2026-04-07 11:07 UTC (permalink / raw)
  To: David E. Box
  Cc: irenic.rajneesh, srinivas.pandruvada, xi.pardee, Hans de Goede,
	LKML, platform-driver-x86

[-- Attachment #1: Type: text/plain, Size: 2111 bytes --]

On Tue, 24 Mar 2026, David E. Box wrote:

> Change PMT class code to pass a discovery index rather than a direct struct
> resource when creating entries. This allows the class to identify the
> discovery source generically without assuming PCI BAR resources. For PCI
> devices, the index still resolves to a resource in the intel_vsec_device.
> Other discovery sources, such as ACPI, can use the same index without
> needing a struct resource.
> 
> Signed-off-by: David E. Box <david.e.box@linux.intel.com>
> ---
> 
> V2 - No changes
> 
>  drivers/platform/x86/intel/pmt/class.c | 6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/platform/x86/intel/pmt/class.c b/drivers/platform/x86/intel/pmt/class.c
> index d652b21261f0..3fcea6a6e763 100644
> --- a/drivers/platform/x86/intel/pmt/class.c
> +++ b/drivers/platform/x86/intel/pmt/class.c
> @@ -207,11 +207,12 @@ EXPORT_SYMBOL_GPL(intel_pmt_class);
>  
>  static int intel_pmt_populate_entry(struct intel_pmt_entry *entry,
>  				    struct intel_vsec_device *ivdev,
> -				    struct resource *disc_res)
> +				    int idx)
>  {
>  	struct pci_dev *pci_dev = to_pci_dev(ivdev->dev);
>  	struct device *dev = &ivdev->auxdev.dev;
>  	struct intel_pmt_header *header = &entry->header;
> +	struct resource *disc_res;
>  	u8 bir;
>  
>  	/*
> @@ -236,6 +237,7 @@ static int intel_pmt_populate_entry(struct intel_pmt_entry *entry,
>  		 * For access_type LOCAL, the base address is as follows:
>  		 * base address = end of discovery region + base offset
>  		 */
> +		disc_res = &ivdev->resource[idx];
>  		entry->base_addr = disc_res->end + 1 + header->base_offset;
>  
>  		/*
> @@ -412,7 +414,7 @@ int intel_pmt_dev_create(struct intel_pmt_entry *entry, struct intel_pmt_namespa
>  			return ret;
>  	}
>  
> -	ret = intel_pmt_populate_entry(entry, intel_vsec_dev, &intel_vsec_dev->resource[idx]);
> +	ret = intel_pmt_populate_entry(entry, intel_vsec_dev, idx);
>  	if (ret)
>  		return ret;
>  
> 

Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>

-- 
 i.

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

* Re: [PATCH V2 06/17] platform/x86/intel/pmt: Unify header fetch and add ACPI source
  2026-03-25  1:48 ` [PATCH V2 06/17] platform/x86/intel/pmt: Unify header fetch and add ACPI source David E. Box
@ 2026-04-07 12:14   ` Ilpo Järvinen
  0 siblings, 0 replies; 27+ messages in thread
From: Ilpo Järvinen @ 2026-04-07 12:14 UTC (permalink / raw)
  To: David E. Box
  Cc: irenic.rajneesh, ilpo.jarvinen, srinivas.pandruvada, xi.pardee,
	hansg, linux-kernel, platform-driver-x86

On Tue, 24 Mar 2026, David E. Box wrote:

> Allow the PMT class to read discovery headers from either PCI MMIO or
> ACPI-provided entries, depending on the discovery source. The new
> source-aware fetch helper retrieves the first two QWORDs for both paths
> while keeping the mapped discovery table available for users such as
> crashlog.
> 
> Split intel_pmt_populate_entry() into source-specific resolvers:
>   - pmt_resolve_access_pci(): handles both ACCESS_LOCAL and ACCESS_BARID
>     for PCI-backed devices and sets entry->pcidev. Same existing
>     functionality.
>   - pmt_resolve_access_acpi(): handles only ACCESS_BARID for ACPI-backed
>     devices, rejecting ACCESS_LOCAL which has no valid semantics without
>     a physical discovery resource.
> 
> This maintains existing PCI behavior and makes no functional changes
> for PCI devices.
> 
> Signed-off-by: David E. Box <david.e.box@linux.intel.com>
> ---
> 
> V2 changes:
> - In pmt_resolve_access_acpi(), moved dev_err() call to single line
>   instead of split across two lines
> - Restructured error handling in intel_pmt_populate_entry(), moving error
>   returns from after switch/case into each case statement for better
>   readability
> - Addressed Ilpo's feedback on error message formatting and error
>   handling patterns
> 
>  drivers/platform/x86/intel/pmt/class.c | 123 +++++++++++++++++++++++--
>  1 file changed, 114 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/platform/x86/intel/pmt/class.c b/drivers/platform/x86/intel/pmt/class.c
> index 3fcea6a6e763..64678f55a20e 100644
> --- a/drivers/platform/x86/intel/pmt/class.c
> +++ b/drivers/platform/x86/intel/pmt/class.c
> @@ -205,9 +205,9 @@ struct class intel_pmt_class = {
>  };
>  EXPORT_SYMBOL_GPL(intel_pmt_class);
>  
> -static int intel_pmt_populate_entry(struct intel_pmt_entry *entry,
> -				    struct intel_vsec_device *ivdev,
> -				    int idx)
> +static int pmt_resolve_access_pci(struct intel_pmt_entry *entry,
> +				  struct intel_vsec_device *ivdev,
> +				  int idx)
>  {
>  	struct pci_dev *pci_dev = to_pci_dev(ivdev->dev);
>  	struct device *dev = &ivdev->auxdev.dev;
> @@ -287,6 +287,81 @@ static int intel_pmt_populate_entry(struct intel_pmt_entry *entry,
>  	}
>  
>  	entry->pcidev = pci_dev;
> +
> +	return 0;
> +}
> +
> +static int pmt_resolve_access_acpi(struct intel_pmt_entry *entry,
> +				   struct intel_vsec_device *ivdev)
> +{
> +	struct pci_dev *pci_dev = NULL;
> +	struct device *dev = &ivdev->auxdev.dev;
> +	struct intel_pmt_header *header = &entry->header;
> +	u8 bir;
> +
> +	if (dev_is_pci(ivdev->dev))
> +		pci_dev = to_pci_dev(ivdev->dev);
> +
> +	/*
> +	 * The base offset should always be 8 byte aligned.
> +	 *
> +	 * For non-local access types the lower 3 bits of base offset
> +	 * contains the index of the base address register where the
> +	 * telemetry can be found.
> +	 */
> +	bir = GET_BIR(header->base_offset);
> +
> +	switch (header->access_type) {
> +	case ACCESS_BARID:
> +		/* ACPI platform drivers use base_addr */
> +		if (ivdev->base_addr) {
> +			entry->base_addr = ivdev->base_addr +
> +					   GET_ADDRESS(header->base_offset);
> +			break;
> +		}
> +
> +		/* If base_addr is not provided, then this is an ACPI companion device */
> +		if (!pci_dev) {
> +			dev_err(dev, "ACCESS_BARID requires PCI BAR resources or base_addr\n");
> +			return -EINVAL;
> +		}
> +
> +		entry->base_addr = pci_resource_start(pci_dev, bir) +
> +			GET_ADDRESS(header->base_offset);

Could you align this to pci_.

> +		break;
> +	default:
> +		dev_err(dev, "Unsupported access type %d for ACPI based PMT\n",
> +			header->access_type);
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static int intel_pmt_populate_entry(struct intel_pmt_entry *entry,
> +				    struct intel_vsec_device *ivdev,
> +				    int idx)
> +{
> +	struct intel_pmt_header *header = &entry->header;
> +	struct device *dev = &ivdev->auxdev.dev;
> +	int ret;
> +
> +	switch (ivdev->src) {
> +	case INTEL_VSEC_DISC_PCI:
> +		ret = pmt_resolve_access_pci(entry, ivdev, idx);
> +		if (ret)
> +			return ret;
> +		break;
> +	case INTEL_VSEC_DISC_ACPI:
> +		ret = pmt_resolve_access_acpi(entry, ivdev);
> +		if (ret)
> +			return ret;
> +		break;
> +	default:
> +		dev_err(dev, "Unknown discovery source: %d\n", ivdev->src);
> +		return -EINVAL;
> +	}
> +
>  	entry->guid = header->guid;
>  	entry->size = header->size;
>  	entry->cb = ivdev->priv_data;
> @@ -371,18 +446,48 @@ static int intel_pmt_dev_register(struct intel_pmt_entry *entry,
>  	return ret;
>  }
>  
> +static int pmt_get_headers(struct intel_vsec_device *ivdev, int idx,
> +			   struct intel_pmt_entry *entry, u64 headers[2])
> +{
> +	struct device *dev = &ivdev->auxdev.dev;
> +
> +	switch (ivdev->src) {
> +	case INTEL_VSEC_DISC_PCI: {
> +		void __iomem *disc_table;
> +
> +		disc_table = devm_ioremap_resource(dev, &ivdev->resource[idx]);
> +		if (IS_ERR(disc_table))
> +			return PTR_ERR(disc_table);
> +
> +		memcpy_fromio(headers, disc_table, 2 * sizeof(u64));
> +
> +		/* Used by crashlog driver */
> +		entry->disc_table = disc_table;
> +
> +		return 0;
> +	}
> +	case INTEL_VSEC_DISC_ACPI:
> +		memcpy(headers, &ivdev->acpi_disc[idx][0], 2 * sizeof(u64));

You seem to repeat literal 2 when you mean the size of the headers so it 
would warrant a define (and perhaps using sizeof(headers) here with the 
memcpy() if it works with headers[2] being passed in as an array, I'm not 
sure how C handles that case).

It was in the earlier patch too as literal.

-- 
 i.

> +
> +		return 0;
> +	default:
> +		dev_err(dev, "Unknown discovery source type: %d\n", ivdev->src);
> +		break;
> +	}
> +
> +	return -EINVAL;
> +}
> +
>  static int pmt_read_header(struct intel_vsec_device *ivdev, int idx,
>  			   struct intel_pmt_entry *entry)
>  {
>  	struct intel_pmt_header *header = &entry->header;
> -	struct device *dev = &ivdev->auxdev.dev;
>  	u64 headers[2];
> +	int ret;
>  
> -	entry->disc_table = devm_ioremap_resource(dev, &ivdev->resource[idx]);
> -	if (IS_ERR(entry->disc_table))
> -		return PTR_ERR(entry->disc_table);
> -
> -	memcpy_fromio(headers, entry->disc_table, 2 * sizeof(u64));
> +	ret = pmt_get_headers(ivdev, idx, entry, headers);
> +	if (ret)
> +		return ret;
>  
>  	header->access_type = FIELD_GET(PMT_ACCESS_TYPE, headers[0]);
>  	header->telem_type = FIELD_GET(PMT_TELEM_TYPE, headers[0]);
> 

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

* Re: [PATCH V2 07/17] platform/x86/intel/pmc: Add PMC SSRAM Kconfig description
  2026-03-25  1:48 ` [PATCH V2 07/17] platform/x86/intel/pmc: Add PMC SSRAM Kconfig description David E. Box
@ 2026-04-07 12:16   ` Ilpo Järvinen
  0 siblings, 0 replies; 27+ messages in thread
From: Ilpo Järvinen @ 2026-04-07 12:16 UTC (permalink / raw)
  To: David E. Box
  Cc: irenic.rajneesh, srinivas.pandruvada, xi.pardee, Hans de Goede,
	LKML, platform-driver-x86

[-- Attachment #1: Type: text/plain, Size: 1233 bytes --]

On Tue, 24 Mar 2026, David E. Box wrote:

> Add a proper description for the intel_pmc_ssram driver.
> 
> Signed-off-by: David E. Box <david.e.box@linux.intel.com>
> ---
> 
> V2 - No changes
> 
>  drivers/platform/x86/intel/pmc/Kconfig | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/drivers/platform/x86/intel/pmc/Kconfig b/drivers/platform/x86/intel/pmc/Kconfig
> index c6ef0bcf76af..0f19dc7edcf9 100644
> --- a/drivers/platform/x86/intel/pmc/Kconfig
> +++ b/drivers/platform/x86/intel/pmc/Kconfig
> @@ -28,3 +28,14 @@ config INTEL_PMC_CORE
>  
>  config INTEL_PMC_SSRAM_TELEMETRY
>  	tristate
> +	help
> +	  This PCI driver discovers PMC SSRAM telemetry regions through the
> +	  PMC's MMIO interface and registers them with the Intel VSEC framework
> +	  as Intel PMT telemetry devices.
> +
> +	  It probes the PMC SSRAM device, extracts DVSEC information from MMIO,
> +	  reads device IDs and base addresses for multiple PMCs (main, IOE, PCH),
> +	  and exposes the discovered telemetry through Intel PMT interfaces
> +	  (including sysfs).
> +
> +	  This option is selected by INTEL_PMC_CORE.
> 

Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>


-- 
 i.

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

* Re: [PATCH V2 08/17] platform/x86/intel/pmc: Add ACPI PWRM telemetry driver for Nova Lake S
  2026-03-25  1:48 ` [PATCH V2 08/17] platform/x86/intel/pmc: Add ACPI PWRM telemetry driver for Nova Lake S David E. Box
@ 2026-04-07 12:56   ` Ilpo Järvinen
  0 siblings, 0 replies; 27+ messages in thread
From: Ilpo Järvinen @ 2026-04-07 12:56 UTC (permalink / raw)
  To: David E. Box
  Cc: irenic.rajneesh, srinivas.pandruvada, xi.pardee, Hans de Goede,
	LKML, platform-driver-x86

On Tue, 24 Mar 2026, David E. Box wrote:

> Add an ACPI-based PMC PWRM telemetry driver for Nova Lake S. The driver
> locates PMT discovery data in _DSD under the Intel VSEC UUID, parses it,
> and registers telemetry regions with the PMT/VSEC framework so PMC
> telemetry is exposed via existing PMT interfaces.
> 
> Export pmc_parse_telem_dsd() and pmc_find_telem_guid() to support ACPI
> discovery in other PMC drivers (e.g., ssram_telemetry) without duplicating
> ACPI parsing logic. Also export acpi_disc_t typedef from core.h for callers
> to properly declare discovery table arrays.
> 
> Selected by INTEL_PMC_CORE. Existing PCI functionality is preserved.
> 
> Signed-off-by: David E. Box <david.e.box@linux.intel.com>
> ---
> 
> V2 changes:
> - Added explicit <linux/uuid.h> include for guid_t type availability in
>   core.h
> - Added explicit <linux/bits.h> include in pwrm_telemetry.c for GENMASK()
> - Added <linux/cleanup.h> and converted goto based cleanup to __free()
>   attributes per Ilpo's feedback
> - Combined u64 hdr0 and u64 hdr1 into single declaration
> - Converted pmc_parse_telem_dsd() to return acpi_disc directly with
>   ERR_PTR() for failures
> - Added braces around _DSD evaluation failure path
> 
>  drivers/platform/x86/intel/pmc/Kconfig        |  14 ++
>  drivers/platform/x86/intel/pmc/Makefile       |   2 +
>  drivers/platform/x86/intel/pmc/core.h         |  15 ++
>  .../platform/x86/intel/pmc/pwrm_telemetry.c   | 214 ++++++++++++++++++
>  4 files changed, 245 insertions(+)
>  create mode 100644 drivers/platform/x86/intel/pmc/pwrm_telemetry.c
> 
> diff --git a/drivers/platform/x86/intel/pmc/Kconfig b/drivers/platform/x86/intel/pmc/Kconfig
> index 0f19dc7edcf9..937186b0b5dd 100644
> --- a/drivers/platform/x86/intel/pmc/Kconfig
> +++ b/drivers/platform/x86/intel/pmc/Kconfig
> @@ -9,6 +9,7 @@ config INTEL_PMC_CORE
>  	depends on ACPI
>  	depends on INTEL_PMT_TELEMETRY
>  	select INTEL_PMC_SSRAM_TELEMETRY
> +	select INTEL_PMC_PWRM_TELEMETRY
>  	help
>  	  The Intel Platform Controller Hub for Intel Core SoCs provides access
>  	  to Power Management Controller registers via various interfaces. This
> @@ -39,3 +40,16 @@ config INTEL_PMC_SSRAM_TELEMETRY
>  	  (including sysfs).
>  
>  	  This option is selected by INTEL_PMC_CORE.
> +
> +config INTEL_PMC_PWRM_TELEMETRY
> +	tristate
> +	help
> +	  This driver discovers PMC PWRM telemetry regions described in ACPI
> +	  _DSD and registers them with the Intel VSEC framework as Intel PMT
> +	  telemetry devices.
> +
> +	  It validates the ACPI discovery data and publishes the discovered
> +	  regions so they can be accessed through the Intel PMT telemetry
> +	  interfaces (including sysfs).
> +
> +	  This option is selected by INTEL_PMC_CORE.
> diff --git a/drivers/platform/x86/intel/pmc/Makefile b/drivers/platform/x86/intel/pmc/Makefile
> index bb960c8721d7..fdbb768f7b09 100644
> --- a/drivers/platform/x86/intel/pmc/Makefile
> +++ b/drivers/platform/x86/intel/pmc/Makefile
> @@ -12,3 +12,5 @@ obj-$(CONFIG_INTEL_PMC_CORE)		+= intel_pmc_core_pltdrv.o
>  # Intel PMC SSRAM driver
>  intel_pmc_ssram_telemetry-y		+= ssram_telemetry.o
>  obj-$(CONFIG_INTEL_PMC_SSRAM_TELEMETRY)	+= intel_pmc_ssram_telemetry.o
> +intel_pmc_pwrm_telemetry-y		+= pwrm_telemetry.o
> +obj-$(CONFIG_INTEL_PMC_PWRM_TELEMETRY)	+= intel_pmc_pwrm_telemetry.o
> diff --git a/drivers/platform/x86/intel/pmc/core.h b/drivers/platform/x86/intel/pmc/core.h
> index 118c8740ad3a..37ea1caf1817 100644
> --- a/drivers/platform/x86/intel/pmc/core.h
> +++ b/drivers/platform/x86/intel/pmc/core.h
> @@ -14,10 +14,14 @@
>  
>  #include <linux/acpi.h>
>  #include <linux/bits.h>
> +#include <linux/cleanup.h>
>  #include <linux/platform_device.h>
> +#include <linux/uuid.h>
>  
>  struct telem_endpoint;
>  
> +DEFINE_FREE(pmc_acpi_free, void *, if (_T) ACPI_FREE(_T))
> +
>  #define SLP_S0_RES_COUNTER_MASK			GENMASK(31, 0)
>  
>  #define PMC_BASE_ADDR_DEFAULT			0xFE000000
> @@ -562,6 +566,8 @@ 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;
>  
> +extern const guid_t intel_vsec_guid;
> +
>  #define pmc_for_each_mode(mode, pmc)						\
>  	for (unsigned int __i = 0, __cond;					\
>  	     __cond = __i < (pmc)->num_lpm_modes,				\
> @@ -583,4 +589,13 @@ static const struct file_operations __name ## _fops = {			\
>  	.release	= single_release,				\
>  }
>  
> +struct intel_vsec_header;
> +union acpi_object;
> +
> +/* Avoid checkpatch warning */
> +typedef u32 (*acpi_disc_t)[4];
> +
> + acpi_disc_t pmc_parse_telem_dsd(union acpi_object *obj,

Remove extra space.

> +			 struct intel_vsec_header *header);

This doesn't seem to align to (.

> +union acpi_object *pmc_find_telem_guid(union acpi_object *dsd);
>  #endif /* PMC_CORE_H */
> diff --git a/drivers/platform/x86/intel/pmc/pwrm_telemetry.c b/drivers/platform/x86/intel/pmc/pwrm_telemetry.c
> new file mode 100644
> index 000000000000..e852ee2d6d9f
> --- /dev/null
> +++ b/drivers/platform/x86/intel/pmc/pwrm_telemetry.c
> @@ -0,0 +1,214 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Intel PMC PWRM ACPI driver
> + *
> + * Copyright (C) 2025, Intel Corporation
> + */
> +
> +#include <linux/acpi.h>
> +#include <linux/bits.h>
> +#include <linux/bitfield.h>
> +#include <linux/cleanup.h>
> +#include <linux/device.h>
> +#include <linux/err.h>
> +#include <linux/errno.h>
> +#include <linux/intel_vsec.h>
> +#include <linux/mod_devicetable.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/resource.h>
> +#include <linux/slab.h>
> +#include <linux/types.h>
> +#include <linux/uuid.h>
> +
> +#include "core.h"
> +
> +#define ENTRY_LEN		5
> +
> +/* DWORD2 */
> +#define DVSEC_ID_MASK		GENMASK(15, 0)
> +#define NUM_ENTRIES_MASK	GENMASK(23, 16)
> +#define ENTRY_SIZE_MASK		GENMASK(31, 24)
> +
> +/* DWORD3 */
> +#define TBIR_MASK		GENMASK(2, 0)
> +#define DISC_TBL_OFF_MASK	GENMASK(31, 3)
> +
> +const guid_t intel_vsec_guid =
> +	GUID_INIT(0x294903fb, 0x634d, 0x4fc7, 0xaf, 0x1f, 0x0f, 0xb9,
> +		  0x56, 0xb0, 0x4f, 0xc1);
> +
> +static bool is_valid_entry(union acpi_object *pkg)
> +{
> +	int i;
> +
> +	if (!pkg || pkg->type != ACPI_TYPE_PACKAGE || pkg->package.count != ENTRY_LEN)
> +		return false;
> +
> +	if (pkg->package.elements[0].type != ACPI_TYPE_STRING)
> +		return false;
> +
> +	for (i = 1; i < ENTRY_LEN; i++)
> +		if (pkg->package.elements[i].type != ACPI_TYPE_INTEGER)
> +			return false;
> +
> +	return true;
> +}
> +
> +u32 (*pmc_parse_telem_dsd(union acpi_object *obj,
> +			  struct intel_vsec_header *header))[4]

Can't you use acpi_disc_t here as well?

> +{
> +	acpi_disc_t disc __free(kfree) = NULL;

This should not be indendepent but at the site of allocation (__free() = 
NULL; is trappy pattern so better avoid it).

> +	union acpi_object *vsec_pkg;
> +	union acpi_object *disc_pkg;
> +	u64 hdr0, hdr1;
> +	int num_regions;
> +	int i;
> +
> +	if (!header)
> +		return ERR_PTR(-EINVAL);
> +
> +	if (!obj || obj->type != ACPI_TYPE_PACKAGE || obj->package.count != 2)
> +		return ERR_PTR(-EINVAL);
> +
> +	/* First Package is DVSEC info */
> +	vsec_pkg = &obj->package.elements[0];
> +	if (!is_valid_entry(vsec_pkg))
> +		return ERR_PTR(-EINVAL);
> +
> +	hdr0 = vsec_pkg->package.elements[3].integer.value;
> +	hdr1 = vsec_pkg->package.elements[4].integer.value;
> +
> +	header->id          = FIELD_GET(DVSEC_ID_MASK, hdr0);
> +	header->num_entries = FIELD_GET(NUM_ENTRIES_MASK, hdr0);
> +	header->entry_size  = FIELD_GET(ENTRY_SIZE_MASK, hdr0);
> +	header->tbir        = FIELD_GET(TBIR_MASK, hdr1);
> +	header->offset      = FIELD_GET(DISC_TBL_OFF_MASK, hdr1);
> +
> +	/* Second Package contains the discovery tables */
> +	disc_pkg = &obj->package.elements[1];
> +	if (disc_pkg->type != ACPI_TYPE_PACKAGE || disc_pkg->package.count < 1)
> +		return ERR_PTR(-EINVAL);
> +
> +	num_regions = disc_pkg->package.count;
> +	if (header->num_entries != num_regions)
> +		return ERR_PTR(-EINVAL);
> +
> +	disc = kmalloc_array(num_regions, sizeof(*disc), GFP_KERNEL);
> +	if (!disc)
> +		return ERR_PTR(-ENOMEM);
> +
> +	for (i = 0; i < num_regions; i++) {
> +		union acpi_object *pkg;
> +		u64 value;
> +		int j;
> +
> +		pkg = &disc_pkg->package.elements[i];
> +		if (!is_valid_entry(pkg))
> +			return ERR_PTR(-EINVAL);
> +
> +		/* Element 0 is a descriptive string; DWORD values start at index 1. */
> +		for (j = 1; j < ENTRY_LEN; j++) {
> +			value = pkg->package.elements[j].integer.value;
> +			if (value > U32_MAX)
> +				return ERR_PTR(-ERANGE);
> +
> +			disc[i][j - 1] = value;
> +		}
> +	}
> +
> +	return no_free_ptr(disc);
> +}
> +EXPORT_SYMBOL_NS_GPL(pmc_parse_telem_dsd, "INTEL_PMC_CORE");


-- 
 i.


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

* Re: [PATCH V2 10/17] platform/x86/intel/pmc/ssram: Use fixed-size static pmc array
  2026-03-25  1:48 ` [PATCH V2 10/17] platform/x86/intel/pmc/ssram: Use fixed-size static pmc array David E. Box
@ 2026-04-07 13:08   ` Ilpo Järvinen
  0 siblings, 0 replies; 27+ messages in thread
From: Ilpo Järvinen @ 2026-04-07 13:08 UTC (permalink / raw)
  To: David E. Box
  Cc: irenic.rajneesh, srinivas.pandruvada, xi.pardee, Hans de Goede,
	LKML, platform-driver-x86

[-- Attachment #1: Type: text/plain, Size: 2185 bytes --]

On Tue, 24 Mar 2026, David E. Box wrote:

> From: Xi Pardee <xi.pardee@linux.intel.com>
> 
> Switch pmc_ssram_telems from a devm-allocated pointer to a fixed-size
> static array, eliminating per-probe allocation overhead and simplifying
> lifetime management.
> 
> Correspondingly simplify pmc_ssram_telemetry_get_pmc_info() validation to
> check devid availability and tighten input bounds checking. Drop
> null-pointer checks now that the storage is static.
> 
> Signed-off-by: Xi Pardee <xi.pardee@linux.intel.com>
> Signed-off-by: David E. Box <david.e.box@linux.intel.com>
> ---
> 
> V2 changes:
> - Replaced hardcoded array size [3] with MAX_NUM_PMC constant
> 
>  drivers/platform/x86/intel/pmc/ssram_telemetry.c | 10 ++--------
>  1 file changed, 2 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/platform/x86/intel/pmc/ssram_telemetry.c b/drivers/platform/x86/intel/pmc/ssram_telemetry.c
> index 1deb4d71da3f..4bfe60ee55ca 100644
> --- a/drivers/platform/x86/intel/pmc/ssram_telemetry.c
> +++ b/drivers/platform/x86/intel/pmc/ssram_telemetry.c
> @@ -24,7 +24,7 @@
>  
>  DEFINE_FREE(pmc_ssram_telemetry_iounmap, void __iomem *, if (_T) iounmap(_T))
>  
> -static struct pmc_ssram_telemetry *pmc_ssram_telems;
> +static struct pmc_ssram_telemetry pmc_ssram_telems[MAX_NUM_PMC];
>  static bool device_probed;
>  
>  static int
> @@ -140,7 +140,7 @@ int pmc_ssram_telemetry_get_pmc_info(unsigned int pmc_idx,
>  	if (pmc_idx >= MAX_NUM_PMC)
>  		return -EINVAL;
>  
> -	if (!pmc_ssram_telems || !pmc_ssram_telems[pmc_idx].devid)
> +	if (!pmc_ssram_telems[pmc_idx].devid)
>  		return -ENODEV;
>  
>  	pmc_ssram_telemetry->devid = pmc_ssram_telems[pmc_idx].devid;
> @@ -153,12 +153,6 @@ static int pmc_ssram_telemetry_probe(struct pci_dev *pcidev, const struct pci_de
>  {
>  	int ret;
>  
> -	pmc_ssram_telems = devm_kzalloc(&pcidev->dev, sizeof(*pmc_ssram_telems) * MAX_NUM_PMC,
> -					GFP_KERNEL);
> -	if (!pmc_ssram_telems) {
> -		ret = -ENOMEM;
> -		goto probe_finish;
> -	}
>  
>  	ret = pcim_enable_device(pcidev);
>  	if (ret) {
> 

Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>

-- 
 i.

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

* Re: [PATCH V2 11/17] platform/x86/intel/pmc/ssram: Refactor DEVID/PWRMBASE extraction into helper
  2026-03-25  1:48 ` [PATCH V2 11/17] platform/x86/intel/pmc/ssram: Refactor DEVID/PWRMBASE extraction into helper David E. Box
@ 2026-04-07 13:18   ` Ilpo Järvinen
  0 siblings, 0 replies; 27+ messages in thread
From: Ilpo Järvinen @ 2026-04-07 13:18 UTC (permalink / raw)
  To: David E. Box
  Cc: irenic.rajneesh, srinivas.pandruvada, xi.pardee, Hans de Goede,
	LKML, platform-driver-x86

[-- Attachment #1: Type: text/plain, Size: 3556 bytes --]

On Tue, 24 Mar 2026, David E. Box wrote:

> Move DEVID/PWRMBASE extraction into pmc_ssram_get_devid_pwrmbase().
> 
> This is a preparatory refactor to place functionality in a common helper
> for reuse by a subsequent patch. Additionally add missing bits.h
> include and define SSRAM_BASE_ADDR_MASK for the address extraction mask.
> 
> Signed-off-by: David E. Box <david.e.box@linux.intel.com>
> ---
> 
> V2 changes:
> - Added missing <linux/bits.h> include for GENMASK_ULL() used in get_base()
> - Defined SSRAM_BASE_ADDR_MASK macro to replace magic mask constant
>   GENMASK_ULL(63, 3)
> 
>  .../platform/x86/intel/pmc/ssram_telemetry.c  | 33 ++++++++++++-------
>  1 file changed, 21 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/platform/x86/intel/pmc/ssram_telemetry.c b/drivers/platform/x86/intel/pmc/ssram_telemetry.c
> index 4bfe60ee55ca..779e84c724ac 100644
> --- a/drivers/platform/x86/intel/pmc/ssram_telemetry.c
> +++ b/drivers/platform/x86/intel/pmc/ssram_telemetry.c
> @@ -5,6 +5,7 @@
>   * Copyright (c) 2023, Intel Corporation.
>   */
>  
> +#include <linux/bits.h>
>  #include <linux/cleanup.h>
>  #include <linux/intel_vsec.h>
>  #include <linux/pci.h>
> @@ -21,12 +22,30 @@
>  #define SSRAM_PCH_OFFSET	0x60
>  #define SSRAM_IOE_OFFSET	0x68
>  #define SSRAM_DEVID_OFFSET	0x70
> +#define SSRAM_BASE_ADDR_MASK	GENMASK_ULL(63, 3)
>  
>  DEFINE_FREE(pmc_ssram_telemetry_iounmap, void __iomem *, if (_T) iounmap(_T))
>  
>  static struct pmc_ssram_telemetry pmc_ssram_telems[MAX_NUM_PMC];
>  static bool device_probed;
>  
> +static inline u64 get_base(void __iomem *addr, u32 offset)
> +{
> +	return lo_hi_readq(addr + offset) & SSRAM_BASE_ADDR_MASK;
> +}
> +
> +static void pmc_ssram_get_devid_pwrmbase(void __iomem *ssram, unsigned int pmc_idx)
> +{
> +	u64 pwrm_base;
> +	u16 devid;
> +
> +	pwrm_base = get_base(ssram, SSRAM_PWRM_OFFSET);
> +	devid = readw(ssram + SSRAM_DEVID_OFFSET);
> +
> +	pmc_ssram_telems[pmc_idx].devid = devid;
> +	pmc_ssram_telems[pmc_idx].base_addr = pwrm_base;
> +}
> +
>  static int
>  pmc_ssram_telemetry_add_pmt(struct pci_dev *pcidev, u64 ssram_base, void __iomem *ssram)
>  {
> @@ -63,18 +82,12 @@ pmc_ssram_telemetry_add_pmt(struct pci_dev *pcidev, u64 ssram_base, void __iomem
>  	return intel_vsec_register(&pcidev->dev, &info);
>  }
>  
> -static inline u64 get_base(void __iomem *addr, u32 offset)
> -{
> -	return lo_hi_readq(addr + offset) & GENMASK_ULL(63, 3);
> -}
> -
>  static int
>  pmc_ssram_telemetry_get_pmc(struct pci_dev *pcidev, unsigned int pmc_idx, u32 offset)
>  {
>  	void __iomem __free(pmc_ssram_telemetry_iounmap) *tmp_ssram = NULL;
>  	void __iomem __free(pmc_ssram_telemetry_iounmap) *ssram = NULL;
> -	u64 ssram_base, pwrm_base;
> -	u16 devid;
> +	u64 ssram_base;
>  
>  	ssram_base = pci_resource_start(pcidev, 0);
>  	tmp_ssram = ioremap(ssram_base, SSRAM_HDR_SIZE);
> @@ -99,11 +112,7 @@ pmc_ssram_telemetry_get_pmc(struct pci_dev *pcidev, unsigned int pmc_idx, u32 of
>  		ssram = no_free_ptr(tmp_ssram);
>  	}
>  
> -	pwrm_base = get_base(ssram, SSRAM_PWRM_OFFSET);
> -	devid = readw(ssram + SSRAM_DEVID_OFFSET);
> -
> -	pmc_ssram_telems[pmc_idx].devid = devid;
> -	pmc_ssram_telems[pmc_idx].base_addr = pwrm_base;
> +	pmc_ssram_get_devid_pwrmbase(ssram, pmc_idx);
>  
>  	/* Find and register and PMC telemetry entries */
>  	return pmc_ssram_telemetry_add_pmt(pcidev, ssram_base, ssram);
> 

Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>

-- 
 i.

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

* Re: [PATCH V2 14/17] platform/x86/intel/pmc/ssram_telemetry: Fix cleanup pattern for __free() variables
  2026-03-25  1:48 ` [PATCH V2 14/17] platform/x86/intel/pmc/ssram_telemetry: Fix cleanup pattern for __free() variables David E. Box
@ 2026-04-07 13:33   ` Ilpo Järvinen
  0 siblings, 0 replies; 27+ messages in thread
From: Ilpo Järvinen @ 2026-04-07 13:33 UTC (permalink / raw)
  To: David E. Box
  Cc: irenic.rajneesh, srinivas.pandruvada, xi.pardee, Hans de Goede,
	LKML, platform-driver-x86

On Tue, 24 Mar 2026, David E. Box wrote:

> Fix improper cleanup.h usage where __free() variables were initialized to
> NULL and then assigned later. Move ssram variable declarations into the
> if/else branches where they're actually assigned to follow the safer
> pattern recommended in cleanup.h.  This change requires also moving the
> pmc_ssram_get_devid_pwrmbase() and add_pmt calls into both if/else branches
> to keep operations within the scope of the local ssram variables.
> 
> Signed-off-by: David E. Box <david.e.box@linux.intel.com>
> ---
> 
> V2 changes:
> - New patch addressing Ilpo's review of cleanup.h patterns
> 
>  .../platform/x86/intel/pmc/ssram_telemetry.c  | 25 +++++++++++--------
>  1 file changed, 15 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/platform/x86/intel/pmc/ssram_telemetry.c b/drivers/platform/x86/intel/pmc/ssram_telemetry.c
> index b329e0c0080b..b1ba17f18ea5 100644
> --- a/drivers/platform/x86/intel/pmc/ssram_telemetry.c
> +++ b/drivers/platform/x86/intel/pmc/ssram_telemetry.c
> @@ -102,12 +102,11 @@ pmc_ssram_telemetry_add_pmt(struct pci_dev *pcidev, u64 ssram_base, void __iomem
>  static int
>  pmc_ssram_telemetry_get_pmc_pci(struct pci_dev *pcidev, unsigned int pmc_idx, u32 offset)
>  {
> -	void __iomem __free(pmc_ssram_telemetry_iounmap) *tmp_ssram = NULL;
> -	void __iomem __free(pmc_ssram_telemetry_iounmap) *ssram = NULL;
>  	u64 ssram_base;
>  
>  	ssram_base = pci_resource_start(pcidev, 0);
> -	tmp_ssram = ioremap(ssram_base, SSRAM_HDR_SIZE);
> +	void __iomem __free(pmc_ssram_telemetry_iounmap) *tmp_ssram =
> +		ioremap(ssram_base, SSRAM_HDR_SIZE);
>  	if (!tmp_ssram)
>  		return -ENOMEM;
>  
> @@ -121,18 +120,24 @@ pmc_ssram_telemetry_get_pmc_pci(struct pci_dev *pcidev, unsigned int pmc_idx, u3
>  		if (!ssram_base)
>  			return 0;
>  
> -		ssram = ioremap(ssram_base, SSRAM_HDR_SIZE);
> +		void __iomem __free(pmc_ssram_telemetry_iounmap) *ssram =
> +			ioremap(ssram_base, SSRAM_HDR_SIZE);
>  		if (!ssram)
>  			return -ENOMEM;
>  
> +		pmc_ssram_get_devid_pwrmbase(ssram, pmc_idx);
> +
> +		/* Find and register and PMC telemetry entries */
> +		return pmc_ssram_telemetry_add_pmt(pcidev, ssram_base, ssram);
>  	} else {
> -		ssram = no_free_ptr(tmp_ssram);
> +		void __iomem __free(pmc_ssram_telemetry_iounmap) *ssram =
> +			no_free_ptr(tmp_ssram);
> +
> +		pmc_ssram_get_devid_pwrmbase(ssram, pmc_idx);
> +
> +		/* Find and register and PMC telemetry entries */
> +		return pmc_ssram_telemetry_add_pmt(pcidev, ssram_base, ssram);
>  	}
> -
> -	pmc_ssram_get_devid_pwrmbase(ssram, pmc_idx);
> -
> -	/* Find and register and PMC telemetry entries */
> -	return pmc_ssram_telemetry_add_pmt(pcidev, ssram_base, ssram);

Hi,

I'm sorry you probably made this because of my request, but this doesn't 
make things simpler so lets stick with having that = NULL outside of the 
inner blocks.

You could have overruled me at your own discretion when you realized you 
have to start duplicating code (and just mention that in the coverletter).

-- 
 i.


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

end of thread, other threads:[~2026-04-07 13:33 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-25  1:48 [PATCH V2 00/17] Add ACPI-based PMT discovery support for Intel PMC David E. Box
2026-03-25  1:48 ` [PATCH V2 01/17] platform/x86/intel/pmt: Add pre/post decode hooks around header parsing David E. Box
2026-03-25  1:48 ` [PATCH V2 02/17] platform/x86/intel/pmt/crashlog: Split init into pre-decode David E. Box
2026-03-25  1:48 ` [PATCH V2 03/17] platform/x86/intel/pmt/telemetry: Move overlap check to post-decode hook David E. Box
2026-04-07 11:05   ` Ilpo Järvinen
2026-03-25  1:48 ` [PATCH V2 04/17] platform/x86/intel/pmt: Move header decode into common helper David E. Box
2026-04-07 11:05   ` Ilpo Järvinen
2026-03-25  1:48 ` [PATCH V2 05/17] platform/x86/intel/pmt: Pass discovery index instead of resource David E. Box
2026-04-07 11:07   ` Ilpo Järvinen
2026-03-25  1:48 ` [PATCH V2 06/17] platform/x86/intel/pmt: Unify header fetch and add ACPI source David E. Box
2026-04-07 12:14   ` Ilpo Järvinen
2026-03-25  1:48 ` [PATCH V2 07/17] platform/x86/intel/pmc: Add PMC SSRAM Kconfig description David E. Box
2026-04-07 12:16   ` Ilpo Järvinen
2026-03-25  1:48 ` [PATCH V2 08/17] platform/x86/intel/pmc: Add ACPI PWRM telemetry driver for Nova Lake S David E. Box
2026-04-07 12:56   ` Ilpo Järvinen
2026-03-25  1:48 ` [PATCH V2 09/17] platform/x86/intel/pmc/ssram: Rename probe and PCI ID table for consistency David E. Box
2026-03-25  1:48 ` [PATCH V2 10/17] platform/x86/intel/pmc/ssram: Use fixed-size static pmc array David E. Box
2026-04-07 13:08   ` Ilpo Järvinen
2026-03-25  1:48 ` [PATCH V2 11/17] platform/x86/intel/pmc/ssram: Refactor DEVID/PWRMBASE extraction into helper David E. Box
2026-04-07 13:18   ` Ilpo Järvinen
2026-03-25  1:48 ` [PATCH V2 12/17] platform/x86/intel/pmc/ssram: Add PCI platform data David E. Box
2026-03-25  1:48 ` [PATCH V2 13/17] platform/x86/intel/pmc/ssram: Refactor memory barrier for reentrant probe David E. Box
2026-03-25  1:48 ` [PATCH V2 14/17] platform/x86/intel/pmc/ssram_telemetry: Fix cleanup pattern for __free() variables David E. Box
2026-04-07 13:33   ` Ilpo Järvinen
2026-03-25  1:48 ` [PATCH V2 15/17] platform/x86/intel/pmc/ssram: Add ACPI discovery scaffolding David E. Box
2026-03-25  1:48 ` [PATCH V2 16/17] platform/x86/intel/pmc/ssram: Make PMT registration optional David E. Box
2026-03-25  1:48 ` [PATCH V2 17/17] platform/x86/intel/pmc: Add NVL PCI IDs for SSRAM telemetry discovery David E. Box

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox