linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH V3 00/15] Intel VSEC/PMT: Introduce Discovery Driver
@ 2025-07-03  2:28 David E. Box
  2025-07-03  2:28 ` [PATCH V3 01/15] MAINTAINERS: Add link to documentation of Intel PMT ABI David E. Box
                   ` (15 more replies)
  0 siblings, 16 replies; 17+ messages in thread
From: David E. Box @ 2025-07-03  2:28 UTC (permalink / raw)
  To: linux-kernel, platform-driver-x86, david.e.box,
	srinivas.pandruvada, andriy.shevchenko, ilpo.jarvinen, tony.luck,
	xi.pardee
  Cc: hdegoede

This patch series introduces a new discovery driver for Intel Platform
Monitoring Technology (PMT) and a set of supporting changes to improve
telemetry integration across Intel VSEC features.

The primary goal of this series is to add the PMT Discovery driver, which
enumerates and exposes telemetry attributes by parsing hardware-provided
discovery tables from OOBMSM devices. In particular, the discovery driver
gathers detailed capability information (such as telemetry region
attributes) that will later enable direct access to telemetry regions via a
new API (intel_pmt_get_regions_by_feature()). This API is crucial for
retrieving data like per-RMID counters.

The remainder of the series consists of several preparatory and testing
patches:

1. Private Data and CPU Mapping:  The VSEC driver now includes
per-device private data to store the OOBMSM-to-CPU mapping. The TPMI driver
copies its platform info into this common area (via
intel_vsec_set_mapping()), allowing other VSEC features to access CPU
mapping information without redundant queries.

2. Device Links Enhancements:  With telemetry now depending on both the
TPMI driver (for CPU mapping) and the new discovery driver (for telemetry
region attributes), device links have been added and optimized. These
changes ensure that supplier drivers are probed and registered before
consumer drivers, enforcing the proper dependency order for reliable
telemetry feature access.

4. Discovery Driver and API:  The core of the series is the addition of
the PMT Discovery driver. This driver not only implements discovery of
telemetry attributes and capability data (exposed via sysfs) but also
introduces an API to retrieve telemetry regions by feature, which is
essential for features like per-RMID telemetry counters.

5. Testing:  A simple KUNIT test is provided for the enhanced discovery
API to ensure its reliability and correctness.

Together, these patches provide a foundation for future telemetry
enhancements in the Intel VSEC framework. They enable a unified interface
for accessing hardware telemetry capabilities and ensure that inter-driver
dependencies are properly managed through device links.

David E. Box (15):
  MAINTAINERS: Add link to documentation of Intel PMT ABI
  platform/x86/intel/vsec: Add private data for per-device data
  platform/x86/intel/vsec: Create wrapper to walk PCI config space
  platform/x86/intel/vsec: Add device links to enforce dependencies
  platform/x86/intel/vsec: Skip absent features during initialization
  platform/x86/intel/vsec: Skip driverless features
  platform/x86/intel/vsec: Add new Discovery feature
  platform/x86/intel/pmt: Add PMT Discovery driver
  docs: Add ABI documentation for intel_pmt feature directories
  platform/x86/intel/tpmi: Relocate platform info to intel_vsec.h
  platform/x86/intel/vsec: Set OOBMSM to CPU mapping
  platform/x86/intel/tpmi: Get OOBMSM CPU mapping from TPMI
  platform/x86/intel/pmt/discovery: Get telemetry attributes
  platform/x86/intel/pmt/telemetry: Add API to retrieve telemetry
    regions by feature
  platform/x86/intel/pmt: KUNIT test for PMT Enhanced Discovery API

 .../testing/sysfs-class-intel_pmt-features    | 134 ++++
 MAINTAINERS                                   |   2 +
 drivers/platform/x86/intel/plr_tpmi.c         |   3 +-
 drivers/platform/x86/intel/pmt/Kconfig        |  27 +
 drivers/platform/x86/intel/pmt/Makefile       |   4 +
 drivers/platform/x86/intel/pmt/class.c        |  35 +-
 drivers/platform/x86/intel/pmt/class.h        |   9 +
 .../platform/x86/intel/pmt/discovery-kunit.c  | 116 ++++
 drivers/platform/x86/intel/pmt/discovery.c    | 635 ++++++++++++++++++
 drivers/platform/x86/intel/pmt/features.c     | 205 ++++++
 drivers/platform/x86/intel/pmt/telemetry.c    |  94 ++-
 .../intel/speed_select_if/isst_tpmi_core.c    |   9 +-
 .../uncore-frequency/uncore-frequency-tpmi.c  |   7 +-
 drivers/platform/x86/intel/vsec.c             | 372 +++++++++-
 drivers/platform/x86/intel/vsec_tpmi.c        |   8 +-
 drivers/powercap/intel_rapl_tpmi.c            |   9 +-
 include/linux/intel_pmt_features.h            | 157 +++++
 include/linux/intel_tpmi.h                    |  27 +-
 include/linux/intel_vsec.h                    |  98 ++-
 19 files changed, 1885 insertions(+), 66 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-class-intel_pmt-features
 create mode 100644 drivers/platform/x86/intel/pmt/discovery-kunit.c
 create mode 100644 drivers/platform/x86/intel/pmt/discovery.c
 create mode 100644 drivers/platform/x86/intel/pmt/features.c
 create mode 100644 include/linux/intel_pmt_features.h


base-commit: d0b3b7b22dfa1f4b515fd3a295b3fd958f9e81af
-- 
2.43.0


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

* [PATCH V3 01/15] MAINTAINERS: Add link to documentation of Intel PMT ABI
  2025-07-03  2:28 [PATCH V3 00/15] Intel VSEC/PMT: Introduce Discovery Driver David E. Box
@ 2025-07-03  2:28 ` David E. Box
  2025-07-03  2:28 ` [PATCH V3 02/15] platform/x86/intel/vsec: Add private data for per-device data David E. Box
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: David E. Box @ 2025-07-03  2:28 UTC (permalink / raw)
  To: linux-kernel, platform-driver-x86, david.e.box,
	srinivas.pandruvada, andriy.shevchenko, ilpo.jarvinen, tony.luck,
	xi.pardee
  Cc: hdegoede

Add a link to the documentation for the Intel Platform Monitoring
Technology ABI in Documentation/ABI/testing/sysfs-class-intel_pmt

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

Changes in v3:
  - No changes

Changes in v2:
  - No changes

 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 4bac4ea21b64..b0a67f058393 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12388,6 +12388,7 @@ F:	include/linux/mfd/intel_soc_pmic*
 INTEL PMT DRIVERS
 M:	David E. Box <david.e.box@linux.intel.com>
 S:	Supported
+F:	Documentation/ABI/testing/sysfs-class-intel_pmt
 F:	drivers/platform/x86/intel/pmt/
 
 INTEL PRO/WIRELESS 2100, 2200BG, 2915ABG NETWORK CONNECTION SUPPORT
-- 
2.43.0


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

* [PATCH V3 02/15] platform/x86/intel/vsec: Add private data for per-device data
  2025-07-03  2:28 [PATCH V3 00/15] Intel VSEC/PMT: Introduce Discovery Driver David E. Box
  2025-07-03  2:28 ` [PATCH V3 01/15] MAINTAINERS: Add link to documentation of Intel PMT ABI David E. Box
@ 2025-07-03  2:28 ` David E. Box
  2025-07-03  2:28 ` [PATCH V3 03/15] platform/x86/intel/vsec: Create wrapper to walk PCI config space David E. Box
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: David E. Box @ 2025-07-03  2:28 UTC (permalink / raw)
  To: linux-kernel, platform-driver-x86, david.e.box,
	srinivas.pandruvada, andriy.shevchenko, ilpo.jarvinen, tony.luck,
	xi.pardee
  Cc: hdegoede

Introduce a new private structure, struct vsec_priv, to hold a pointer to
the platform-specific information. Although the driver didn’t previously
require this per-device data, adding it now lays the groundwork for
upcoming patches that will manage such data. No functional changes.

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

Changes in v3:
  - No changes

Changes in v2:
  - No changes

 drivers/platform/x86/intel/vsec.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/drivers/platform/x86/intel/vsec.c b/drivers/platform/x86/intel/vsec.c
index 055ca9f48fb4..59fb6568a855 100644
--- a/drivers/platform/x86/intel/vsec.c
+++ b/drivers/platform/x86/intel/vsec.c
@@ -32,6 +32,10 @@ static DEFINE_IDA(intel_vsec_ida);
 static DEFINE_IDA(intel_vsec_sdsi_ida);
 static DEFINE_XARRAY_ALLOC(auxdev_array);
 
+struct vsec_priv {
+	struct intel_vsec_platform_info *info;
+};
+
 static const char *intel_vsec_name(enum intel_vsec_id id)
 {
 	switch (id) {
@@ -348,6 +352,7 @@ EXPORT_SYMBOL_NS_GPL(intel_vsec_register, "INTEL_VSEC");
 static int intel_vsec_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	struct intel_vsec_platform_info *info;
+	struct vsec_priv *priv;
 	bool have_devices = false;
 	int ret;
 
@@ -360,6 +365,13 @@ static int intel_vsec_pci_probe(struct pci_dev *pdev, const struct pci_device_id
 	if (!info)
 		return -EINVAL;
 
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->info = info;
+	pci_set_drvdata(pdev, priv);
+
 	if (intel_vsec_walk_dvsec(pdev, info))
 		have_devices = true;
 
-- 
2.43.0


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

* [PATCH V3 03/15] platform/x86/intel/vsec: Create wrapper to walk PCI config space
  2025-07-03  2:28 [PATCH V3 00/15] Intel VSEC/PMT: Introduce Discovery Driver David E. Box
  2025-07-03  2:28 ` [PATCH V3 01/15] MAINTAINERS: Add link to documentation of Intel PMT ABI David E. Box
  2025-07-03  2:28 ` [PATCH V3 02/15] platform/x86/intel/vsec: Add private data for per-device data David E. Box
@ 2025-07-03  2:28 ` David E. Box
  2025-07-03  2:28 ` [PATCH V3 04/15] platform/x86/intel/vsec: Add device links to enforce dependencies David E. Box
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: David E. Box @ 2025-07-03  2:28 UTC (permalink / raw)
  To: linux-kernel, platform-driver-x86, david.e.box,
	srinivas.pandruvada, andriy.shevchenko, ilpo.jarvinen, tony.luck,
	xi.pardee
  Cc: hdegoede

Combine three PCI config space walkers — intel_vsec_walk_dvsec(),
intel_vsec_walk_vsec(), and intel_vsec_walk_header() — into a new wrapper
function, intel_vsec_feature_walk().  This refactoring simplifies the probe
logic and lays the groundwork for future patches that will loop over these
calls. No functional changes.

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

Changes in v3:
  - Rename intel_vsec_feature_walk() to intel_vsec_get_features() and
    have it return bool instead of passing as an argument

Changes in v2:
  - No changes

 drivers/platform/x86/intel/vsec.c | 38 +++++++++++++++++++++----------
 1 file changed, 26 insertions(+), 12 deletions(-)

diff --git a/drivers/platform/x86/intel/vsec.c b/drivers/platform/x86/intel/vsec.c
index 59fb6568a855..8bdb74d86f24 100644
--- a/drivers/platform/x86/intel/vsec.c
+++ b/drivers/platform/x86/intel/vsec.c
@@ -349,11 +349,35 @@ int intel_vsec_register(struct pci_dev *pdev,
 }
 EXPORT_SYMBOL_NS_GPL(intel_vsec_register, "INTEL_VSEC");
 
+static bool intel_vsec_get_features(struct pci_dev *pdev,
+				    struct intel_vsec_platform_info *info)
+{
+	bool found = false;
+
+	/*
+	 * Both DVSEC and VSEC capabilities can exist on the same device,
+	 * so both intel_vsec_walk_dvsec() and intel_vsec_walk_vsec() must be
+	 * called independently. Additionally, intel_vsec_walk_header() is
+	 * needed for devices that do not have VSEC/DVSEC but provide the
+	 * information via device_data.
+	 */
+	if (intel_vsec_walk_dvsec(pdev, info))
+		found = true;
+
+	if (intel_vsec_walk_vsec(pdev, info))
+		found = true;
+
+	if (info && (info->quirks & VSEC_QUIRK_NO_DVSEC) &&
+	    intel_vsec_walk_header(pdev, info))
+		found = true;
+
+	return found;
+}
+
 static int intel_vsec_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	struct intel_vsec_platform_info *info;
 	struct vsec_priv *priv;
-	bool have_devices = false;
 	int ret;
 
 	ret = pcim_enable_device(pdev);
@@ -372,17 +396,7 @@ static int intel_vsec_pci_probe(struct pci_dev *pdev, const struct pci_device_id
 	priv->info = info;
 	pci_set_drvdata(pdev, priv);
 
-	if (intel_vsec_walk_dvsec(pdev, info))
-		have_devices = true;
-
-	if (intel_vsec_walk_vsec(pdev, info))
-		have_devices = true;
-
-	if (info && (info->quirks & VSEC_QUIRK_NO_DVSEC) &&
-	    intel_vsec_walk_header(pdev, info))
-		have_devices = true;
-
-	if (!have_devices)
+	if (!intel_vsec_get_features(pdev, info))
 		return -ENODEV;
 
 	return 0;
-- 
2.43.0


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

* [PATCH V3 04/15] platform/x86/intel/vsec: Add device links to enforce dependencies
  2025-07-03  2:28 [PATCH V3 00/15] Intel VSEC/PMT: Introduce Discovery Driver David E. Box
                   ` (2 preceding siblings ...)
  2025-07-03  2:28 ` [PATCH V3 03/15] platform/x86/intel/vsec: Create wrapper to walk PCI config space David E. Box
@ 2025-07-03  2:28 ` David E. Box
  2025-07-03  2:28 ` [PATCH V3 05/15] platform/x86/intel/vsec: Skip absent features during initialization David E. Box
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: David E. Box @ 2025-07-03  2:28 UTC (permalink / raw)
  To: linux-kernel, platform-driver-x86, david.e.box,
	srinivas.pandruvada, andriy.shevchenko, ilpo.jarvinen, tony.luck,
	xi.pardee
  Cc: hdegoede

New Intel VSEC features will have dependencies on other features, requiring
certain supplier drivers to be probed before their consumers. To enforce
this dependency ordering, introduce device links using device_link_add(),
ensuring that suppliers are fully registered before consumers are probed.

- Add device link tracking by storing supplier devices and tracking their
  state.
- Implement intel_vsec_link_devices() to establish links between suppliers
  and consumers based on feature dependencies.
- Add get_consumer_dependencies() to retrieve supplier-consumer
  relationships.
- Modify feature registration logic:
  * Consumers now check that all required suppliers are registered before
    being initialized.
  * suppliers_ready() verifies that all required supplier devices are
    available.
- Prevent potential null consumer name issue in sysfs:
  - Use dev_set_name() when creating auxiliary devices to ensure a
    unique, non-null consumer name.
- Update intel_vsec_pci_probe() to loop up to the number of possible
  features or when all devices are registered, whichever comes first.
- Introduce VSEC_CAP_UNUSED to prevent sub-features (registered via
  exported APIs) from being mistakenly linked.

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

Changes in v3:
  - In suppliers_ready() add WARN_ON_ONCE on feature check. Also include
    bug.h
  - Add found_any bool to check the return value from
    intel_vsec_get_features() and return -ENODEV if none were ever
    found.

Changes in v2:
  - Simplify dependency search in get_consumer_dependencies() per comments
    from Ilpo.
  - Add rollback for auxiliary_device_uninit() in intel_vsec_add_aux().
  - In suppliers_ready() clarify that for_each_set_bit() is searching for
    all *ready* suppliers, not all suppliers. If any is not ready and not
    ignored, it immediately returns.
  - In suppliers_ready() check device_link_add() return status.
  - In intel_vsec_probe() uses info->caps consistently.
  - Fix spelling errors and remove unrelated changes.

 drivers/platform/x86/intel/vsec.c | 223 ++++++++++++++++++++++++++++--
 include/linux/intel_vsec.h        |  28 +++-
 2 files changed, 236 insertions(+), 15 deletions(-)

diff --git a/drivers/platform/x86/intel/vsec.c b/drivers/platform/x86/intel/vsec.c
index 8bdb74d86f24..aa1f7e63039d 100644
--- a/drivers/platform/x86/intel/vsec.c
+++ b/drivers/platform/x86/intel/vsec.c
@@ -15,9 +15,12 @@
 
 #include <linux/auxiliary_bus.h>
 #include <linux/bits.h>
+#include <linux/bitops.h>
+#include <linux/bug.h>
 #include <linux/cleanup.h>
 #include <linux/delay.h>
 #include <linux/idr.h>
+#include <linux/log2.h>
 #include <linux/intel_vsec.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -32,8 +35,17 @@ static DEFINE_IDA(intel_vsec_ida);
 static DEFINE_IDA(intel_vsec_sdsi_ida);
 static DEFINE_XARRAY_ALLOC(auxdev_array);
 
+enum vsec_device_state {
+	STATE_NOT_FOUND,
+	STATE_REGISTERED,
+	STATE_SKIP,
+};
+
 struct vsec_priv {
 	struct intel_vsec_platform_info *info;
+	struct device *suppliers[VSEC_FEATURE_COUNT];
+	enum vsec_device_state state[VSEC_FEATURE_COUNT];
+	unsigned long found_caps;
 };
 
 static const char *intel_vsec_name(enum intel_vsec_id id)
@@ -95,6 +107,74 @@ static void intel_vsec_dev_release(struct device *dev)
 	kfree(intel_vsec_dev);
 }
 
+static const struct vsec_feature_dependency *
+get_consumer_dependencies(struct vsec_priv *priv, int cap_id)
+{
+	const struct vsec_feature_dependency *deps = priv->info->deps;
+	int consumer_id = priv->info->num_deps;
+
+	if (!deps)
+		return NULL;
+
+	while (consumer_id--)
+		if (deps[consumer_id].feature == BIT(cap_id))
+			return &deps[consumer_id];
+
+	return NULL;
+}
+
+/*
+ * Although pci_device_id table is available in the pdev, this prototype is
+ * necessary because the code using it can be called by an exported API that
+ * might pass a different pdev.
+ */
+static const struct pci_device_id intel_vsec_pci_ids[];
+
+static int intel_vsec_link_devices(struct pci_dev *pdev, struct device *dev,
+				   int consumer_id)
+{
+	const struct vsec_feature_dependency *deps;
+	enum vsec_device_state *state;
+	struct device **suppliers;
+	struct vsec_priv *priv;
+	int supplier_id;
+
+	if (!consumer_id)
+		return 0;
+
+	if (!pci_match_id(intel_vsec_pci_ids, pdev))
+		return 0;
+
+	priv = pci_get_drvdata(pdev);
+	state = priv->state;
+	suppliers = priv->suppliers;
+
+	priv->suppliers[consumer_id] = dev;
+
+	deps = get_consumer_dependencies(priv, consumer_id);
+	if (!deps)
+		return 0;
+
+	for_each_set_bit(supplier_id, &deps->supplier_bitmap, VSEC_FEATURE_COUNT) {
+		struct device_link *link;
+
+		if (state[supplier_id] != STATE_REGISTERED)
+			continue;
+
+		if (!suppliers[supplier_id]) {
+			dev_err(dev, "Bad supplier list\n");
+			return -EINVAL;
+		}
+
+		link = device_link_add(dev, suppliers[supplier_id],
+				       DL_FLAG_AUTOPROBE_CONSUMER);
+		if (!link)
+			return -EINVAL;
+	}
+
+	return 0;
+}
+
 int intel_vsec_add_aux(struct pci_dev *pdev, struct device *parent,
 		       struct intel_vsec_device *intel_vsec_dev,
 		       const char *name)
@@ -132,19 +212,37 @@ int intel_vsec_add_aux(struct pci_dev *pdev, struct device *parent,
 		return ret;
 	}
 
+	/*
+	 * Assign a name now to ensure that the device link doesn't contain
+	 * a null string for the consumer name. This is a problem when a supplier
+	 * supplies more than one consumer and can lead to a duplicate name error
+	 * when the link is created in sysfs.
+	 */
+	ret = dev_set_name(&auxdev->dev, "%s.%s.%d", KBUILD_MODNAME, auxdev->name,
+			   auxdev->id);
+	if (ret)
+		goto cleanup_aux;
+
+	ret = intel_vsec_link_devices(pdev, &auxdev->dev, intel_vsec_dev->cap_id);
+	if (ret)
+		goto cleanup_aux;
+
 	ret = auxiliary_device_add(auxdev);
-	if (ret < 0) {
-		auxiliary_device_uninit(auxdev);
-		return ret;
-	}
+	if (ret)
+		goto cleanup_aux;
 
 	return devm_add_action_or_reset(parent, intel_vsec_remove_aux,
 				       auxdev);
+
+cleanup_aux:
+	auxiliary_device_uninit(auxdev);
+	return ret;
 }
 EXPORT_SYMBOL_NS_GPL(intel_vsec_add_aux, "INTEL_VSEC");
 
 static int intel_vsec_add_dev(struct pci_dev *pdev, struct intel_vsec_header *header,
-			      struct intel_vsec_platform_info *info)
+			      struct intel_vsec_platform_info *info,
+			      unsigned long cap_id)
 {
 	struct intel_vsec_device __free(kfree) *intel_vsec_dev = NULL;
 	struct resource __free(kfree) *res = NULL;
@@ -211,6 +309,7 @@ static int intel_vsec_add_dev(struct pci_dev *pdev, struct intel_vsec_header *he
 	intel_vsec_dev->quirks = info->quirks;
 	intel_vsec_dev->base_addr = info->base_addr;
 	intel_vsec_dev->priv_data = info->priv_data;
+	intel_vsec_dev->cap_id = cap_id;
 
 	if (header->id == VSEC_ID_SDSI)
 		intel_vsec_dev->ida = &intel_vsec_sdsi_ida;
@@ -225,6 +324,101 @@ static int intel_vsec_add_dev(struct pci_dev *pdev, struct intel_vsec_header *he
 				  intel_vsec_name(header->id));
 }
 
+static bool suppliers_ready(struct vsec_priv *priv,
+			    const struct vsec_feature_dependency *consumer_deps,
+			    int cap_id)
+{
+	enum vsec_device_state *state = priv->state;
+	int supplier_id;
+
+	if (WARN_ON_ONCE(consumer_deps->feature != BIT(cap_id)))
+		return false;
+
+	/*
+	 * Verify that all required suppliers have been found. Return false
+	 * immediately if any are still missing.
+	 */
+	for_each_set_bit(supplier_id, &consumer_deps->supplier_bitmap, VSEC_FEATURE_COUNT) {
+		if (state[supplier_id] == STATE_SKIP)
+			continue;
+
+		if (state[supplier_id] == STATE_NOT_FOUND)
+			return false;
+	}
+
+	/*
+	 * All suppliers have been found and the consumer is ready to be
+	 * registered.
+	 */
+	return true;
+}
+
+static int get_cap_id(u32 header_id, unsigned long *cap_id)
+{
+	switch (header_id) {
+	case VSEC_ID_TELEMETRY:
+		*cap_id = ilog2(VSEC_CAP_TELEMETRY);
+		break;
+	case VSEC_ID_WATCHER:
+		*cap_id = ilog2(VSEC_CAP_WATCHER);
+		break;
+	case VSEC_ID_CRASHLOG:
+		*cap_id = ilog2(VSEC_CAP_CRASHLOG);
+		break;
+	case VSEC_ID_SDSI:
+		*cap_id = ilog2(VSEC_CAP_SDSI);
+		break;
+	case VSEC_ID_TPMI:
+		*cap_id = ilog2(VSEC_CAP_TPMI);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int intel_vsec_register_device(struct pci_dev *pdev,
+				      struct intel_vsec_header *header,
+				      struct intel_vsec_platform_info *info)
+{
+	const struct vsec_feature_dependency *consumer_deps;
+	struct vsec_priv *priv;
+	unsigned long cap_id;
+	int ret;
+
+	ret = get_cap_id(header->id, &cap_id);
+	if (ret)
+		return ret;
+
+	/*
+	 * Only track dependencies for devices probed by the VSEC driver.
+	 * For others using the exported APIs, add the device directly.
+	 */
+	if (!pci_match_id(intel_vsec_pci_ids, pdev))
+		return intel_vsec_add_dev(pdev, header, info, cap_id);
+
+	priv = pci_get_drvdata(pdev);
+	if (priv->state[cap_id] == STATE_REGISTERED ||
+	    priv->state[cap_id] == STATE_SKIP)
+		return -EEXIST;
+
+	priv->found_caps |= BIT(cap_id);
+
+	consumer_deps = get_consumer_dependencies(priv, cap_id);
+	if (!consumer_deps || suppliers_ready(priv, consumer_deps, cap_id)) {
+		ret = intel_vsec_add_dev(pdev, header, info, cap_id);
+		if (ret)
+			priv->state[cap_id] = STATE_SKIP;
+		else
+			priv->state[cap_id] = STATE_REGISTERED;
+
+		return ret;
+	}
+
+	return -EAGAIN;
+}
+
 static bool intel_vsec_walk_header(struct pci_dev *pdev,
 				   struct intel_vsec_platform_info *info)
 {
@@ -233,7 +427,7 @@ static bool intel_vsec_walk_header(struct pci_dev *pdev,
 	int ret;
 
 	for ( ; *header; header++) {
-		ret = intel_vsec_add_dev(pdev, *header, info);
+		ret = intel_vsec_register_device(pdev, *header, info);
 		if (!ret)
 			have_devices = true;
 	}
@@ -281,7 +475,7 @@ static bool intel_vsec_walk_dvsec(struct pci_dev *pdev,
 		pci_read_config_dword(pdev, pos + PCI_DVSEC_HEADER2, &hdr);
 		header.id = PCI_DVSEC_HEADER2_ID(hdr);
 
-		ret = intel_vsec_add_dev(pdev, &header, info);
+		ret = intel_vsec_register_device(pdev, &header, info);
 		if (ret)
 			continue;
 
@@ -326,7 +520,7 @@ static bool intel_vsec_walk_vsec(struct pci_dev *pdev,
 		header.tbir = INTEL_DVSEC_TABLE_BAR(table);
 		header.offset = INTEL_DVSEC_TABLE_OFFSET(table);
 
-		ret = intel_vsec_add_dev(pdev, &header, info);
+		ret = intel_vsec_register_device(pdev, &header, info);
 		if (ret)
 			continue;
 
@@ -378,7 +572,8 @@ static int intel_vsec_pci_probe(struct pci_dev *pdev, const struct pci_device_id
 {
 	struct intel_vsec_platform_info *info;
 	struct vsec_priv *priv;
-	int ret;
+	int num_caps, ret;
+	bool found_any = false;
 
 	ret = pcim_enable_device(pdev);
 	if (ret)
@@ -396,7 +591,15 @@ static int intel_vsec_pci_probe(struct pci_dev *pdev, const struct pci_device_id
 	priv->info = info;
 	pci_set_drvdata(pdev, priv);
 
-	if (!intel_vsec_get_features(pdev, info))
+	num_caps = hweight_long(info->caps);
+	while (num_caps--) {
+		found_any |= intel_vsec_get_features(pdev, info);
+
+		if (priv->found_caps == info->caps)
+			break;
+	}
+
+	if (!found_any)
 		return -ENODEV;
 
 	return 0;
diff --git a/include/linux/intel_vsec.h b/include/linux/intel_vsec.h
index bc95821f1bfb..71067afaca99 100644
--- a/include/linux/intel_vsec.h
+++ b/include/linux/intel_vsec.h
@@ -5,11 +5,18 @@
 #include <linux/auxiliary_bus.h>
 #include <linux/bits.h>
 
-#define VSEC_CAP_TELEMETRY	BIT(0)
-#define VSEC_CAP_WATCHER	BIT(1)
-#define VSEC_CAP_CRASHLOG	BIT(2)
-#define VSEC_CAP_SDSI		BIT(3)
-#define VSEC_CAP_TPMI		BIT(4)
+/*
+ * VSEC_CAP_UNUSED is reserved. It exists to prevent zero initialized
+ * intel_vsec devices from being automatically set to a known
+ * capability with ID 0
+ */
+#define VSEC_CAP_UNUSED		BIT(0)
+#define VSEC_CAP_TELEMETRY	BIT(1)
+#define VSEC_CAP_WATCHER	BIT(2)
+#define VSEC_CAP_CRASHLOG	BIT(3)
+#define VSEC_CAP_SDSI		BIT(4)
+#define VSEC_CAP_TPMI		BIT(5)
+#define VSEC_FEATURE_COUNT	6
 
 /* Intel DVSEC offsets */
 #define INTEL_DVSEC_ENTRIES		0xA
@@ -81,22 +88,31 @@ struct pmt_callbacks {
 	int (*read_telem)(struct pci_dev *pdev, u32 guid, u64 *data, loff_t off, u32 count);
 };
 
+struct vsec_feature_dependency {
+	unsigned long feature;
+	unsigned long supplier_bitmap;
+};
+
 /**
  * struct intel_vsec_platform_info - Platform specific data
  * @parent:    parent device in the auxbus chain
  * @headers:   list of headers to define the PMT client devices to create
+ * @deps:      array of feature dependencies
  * @priv_data: private data, usable by parent devices, currently a callback
  * @caps:      bitmask of PMT capabilities for the given headers
  * @quirks:    bitmask of VSEC device quirks
  * @base_addr: allow a base address to be specified (rather than derived)
+ * @num_deps:  Count feature dependencies
  */
 struct intel_vsec_platform_info {
 	struct device *parent;
 	struct intel_vsec_header **headers;
+	const struct vsec_feature_dependency *deps;
 	void *priv_data;
 	unsigned long caps;
 	unsigned long quirks;
 	u64 base_addr;
+	int num_deps;
 };
 
 /**
@@ -110,6 +126,7 @@ struct intel_vsec_platform_info {
  * @priv_data:     any private data needed
  * @quirks:        specified quirks
  * @base_addr:     base address of entries (if specified)
+ * @cap_id:        the enumerated id of the vsec feature
  */
 struct intel_vsec_device {
 	struct auxiliary_device auxdev;
@@ -122,6 +139,7 @@ struct intel_vsec_device {
 	size_t priv_data_size;
 	unsigned long quirks;
 	u64 base_addr;
+	unsigned long cap_id;
 };
 
 int intel_vsec_add_aux(struct pci_dev *pdev, struct device *parent,
-- 
2.43.0


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

* [PATCH V3 05/15] platform/x86/intel/vsec: Skip absent features during initialization
  2025-07-03  2:28 [PATCH V3 00/15] Intel VSEC/PMT: Introduce Discovery Driver David E. Box
                   ` (3 preceding siblings ...)
  2025-07-03  2:28 ` [PATCH V3 04/15] platform/x86/intel/vsec: Add device links to enforce dependencies David E. Box
@ 2025-07-03  2:28 ` David E. Box
  2025-07-03  2:28 ` [PATCH V3 06/15] platform/x86/intel/vsec: Skip driverless features David E. Box
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: David E. Box @ 2025-07-03  2:28 UTC (permalink / raw)
  To: linux-kernel, platform-driver-x86, david.e.box,
	srinivas.pandruvada, andriy.shevchenko, ilpo.jarvinen, tony.luck,
	xi.pardee
  Cc: hdegoede

Some VSEC features depend on the presence of supplier features that may not
always be present. To prevent unnecessary retries and device linking during
initialization, introduce logic to skip attempts to link consumers to
missing suppliers.

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

Changes in v3:
  - No changes

Changes in v2:
  - No changes

 drivers/platform/x86/intel/vsec.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/drivers/platform/x86/intel/vsec.c b/drivers/platform/x86/intel/vsec.c
index aa1f7e63039d..32f777b41b33 100644
--- a/drivers/platform/x86/intel/vsec.c
+++ b/drivers/platform/x86/intel/vsec.c
@@ -568,11 +568,30 @@ static bool intel_vsec_get_features(struct pci_dev *pdev,
 	return found;
 }
 
+static void intel_vsec_skip_missing_dependencies(struct pci_dev *pdev)
+{
+	struct vsec_priv *priv = pci_get_drvdata(pdev);
+	const struct vsec_feature_dependency *deps = priv->info->deps;
+	int consumer_id = priv->info->num_deps;
+
+	while (consumer_id--) {
+		int supplier_id;
+
+		deps = &priv->info->deps[consumer_id];
+
+		for_each_set_bit(supplier_id, &deps->supplier_bitmap, VSEC_FEATURE_COUNT) {
+			if (!(BIT(supplier_id) & priv->found_caps))
+				priv->state[supplier_id] = STATE_SKIP;
+		}
+	}
+}
+
 static int intel_vsec_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	struct intel_vsec_platform_info *info;
 	struct vsec_priv *priv;
 	int num_caps, ret;
+	int run_once = 0;
 	bool found_any = false;
 
 	ret = pcim_enable_device(pdev);
@@ -597,6 +616,11 @@ static int intel_vsec_pci_probe(struct pci_dev *pdev, const struct pci_device_id
 
 		if (priv->found_caps == info->caps)
 			break;
+
+		if (!run_once) {
+			intel_vsec_skip_missing_dependencies(pdev);
+			run_once = 1;
+		}
 	}
 
 	if (!found_any)
-- 
2.43.0


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

* [PATCH V3 06/15] platform/x86/intel/vsec: Skip driverless features
  2025-07-03  2:28 [PATCH V3 00/15] Intel VSEC/PMT: Introduce Discovery Driver David E. Box
                   ` (4 preceding siblings ...)
  2025-07-03  2:28 ` [PATCH V3 05/15] platform/x86/intel/vsec: Skip absent features during initialization David E. Box
@ 2025-07-03  2:28 ` David E. Box
  2025-07-03  2:28 ` [PATCH V3 07/15] platform/x86/intel/vsec: Add new Discovery feature David E. Box
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: David E. Box @ 2025-07-03  2:28 UTC (permalink / raw)
  To: linux-kernel, platform-driver-x86, david.e.box,
	srinivas.pandruvada, andriy.shevchenko, ilpo.jarvinen, tony.luck,
	xi.pardee
  Cc: hdegoede

If a feature lacks a corresponding driver and that feature is also a
supplier, registering it would be prevent the consumer driver from probing.
Introduces logic to skip such features during device registration.

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

Changes in v3:
  - No changes

Changes in v2:
  - No changes

 drivers/platform/x86/intel/vsec.c | 28 +++++++++++++++++++++++++++-
 1 file changed, 27 insertions(+), 1 deletion(-)

diff --git a/drivers/platform/x86/intel/vsec.c b/drivers/platform/x86/intel/vsec.c
index 32f777b41b33..30e558af6888 100644
--- a/drivers/platform/x86/intel/vsec.c
+++ b/drivers/platform/x86/intel/vsec.c
@@ -123,6 +123,26 @@ get_consumer_dependencies(struct vsec_priv *priv, int cap_id)
 	return NULL;
 }
 
+static bool vsec_driver_present(int cap_id)
+{
+	unsigned long bit = BIT(cap_id);
+
+	switch (bit) {
+	case VSEC_CAP_TELEMETRY:
+		return IS_ENABLED(CONFIG_INTEL_PMT_TELEMETRY);
+	case VSEC_CAP_WATCHER:
+		return IS_ENABLED(CONFIG_INTEL_PMT_WATCHER);
+	case VSEC_CAP_CRASHLOG:
+		return IS_ENABLED(CONFIG_INTEL_PMT_CRASHLOG);
+	case VSEC_CAP_SDSI:
+		return IS_ENABLED(CONFIG_INTEL_SDSI);
+	case VSEC_CAP_TPMI:
+		return IS_ENABLED(CONFIG_INTEL_TPMI);
+	default:
+		return false;
+	}
+}
+
 /*
  * Although pci_device_id table is available in the pdev, this prototype is
  * necessary because the code using it can be called by an exported API that
@@ -158,7 +178,8 @@ static int intel_vsec_link_devices(struct pci_dev *pdev, struct device *dev,
 	for_each_set_bit(supplier_id, &deps->supplier_bitmap, VSEC_FEATURE_COUNT) {
 		struct device_link *link;
 
-		if (state[supplier_id] != STATE_REGISTERED)
+		if (state[supplier_id] != STATE_REGISTERED ||
+		    !vsec_driver_present(supplier_id))
 			continue;
 
 		if (!suppliers[supplier_id]) {
@@ -405,6 +426,11 @@ static int intel_vsec_register_device(struct pci_dev *pdev,
 
 	priv->found_caps |= BIT(cap_id);
 
+	if (!vsec_driver_present(cap_id)) {
+		priv->state[cap_id] = STATE_SKIP;
+		return -ENODEV;
+	}
+
 	consumer_deps = get_consumer_dependencies(priv, cap_id);
 	if (!consumer_deps || suppliers_ready(priv, consumer_deps, cap_id)) {
 		ret = intel_vsec_add_dev(pdev, header, info, cap_id);
-- 
2.43.0


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

* [PATCH V3 07/15] platform/x86/intel/vsec: Add new Discovery feature
  2025-07-03  2:28 [PATCH V3 00/15] Intel VSEC/PMT: Introduce Discovery Driver David E. Box
                   ` (5 preceding siblings ...)
  2025-07-03  2:28 ` [PATCH V3 06/15] platform/x86/intel/vsec: Skip driverless features David E. Box
@ 2025-07-03  2:28 ` David E. Box
  2025-07-03  2:28 ` [PATCH V3 08/15] platform/x86/intel/pmt: Add PMT Discovery driver David E. Box
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: David E. Box @ 2025-07-03  2:28 UTC (permalink / raw)
  To: linux-kernel, platform-driver-x86, david.e.box,
	srinivas.pandruvada, andriy.shevchenko, ilpo.jarvinen, tony.luck,
	xi.pardee
  Cc: hdegoede

Add the PCIe VSEC ID for new Intel Platform Monitoring Technology
Capability Discovery feature. Discovery provides detailed information for
the various Intel VSEC features. Also make the driver a supplier for
TPMI and Telemetry drivers which will use the information.

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

Changes in v3:
  - No changes

Changes in v2:
  - Add missing comma in oobmsm_deps[]

 drivers/platform/x86/intel/vsec.c | 26 ++++++++++++++++++++++++--
 include/linux/intel_vsec.h        |  4 +++-
 2 files changed, 27 insertions(+), 3 deletions(-)

diff --git a/drivers/platform/x86/intel/vsec.c b/drivers/platform/x86/intel/vsec.c
index 30e558af6888..4d76f1ac3c8c 100644
--- a/drivers/platform/x86/intel/vsec.c
+++ b/drivers/platform/x86/intel/vsec.c
@@ -66,6 +66,9 @@ static const char *intel_vsec_name(enum intel_vsec_id id)
 	case VSEC_ID_TPMI:
 		return "tpmi";
 
+	case VSEC_ID_DISCOVERY:
+		return "discovery";
+
 	default:
 		return NULL;
 	}
@@ -84,6 +87,8 @@ static bool intel_vsec_supported(u16 id, unsigned long caps)
 		return !!(caps & VSEC_CAP_SDSI);
 	case VSEC_ID_TPMI:
 		return !!(caps & VSEC_CAP_TPMI);
+	case VSEC_ID_DISCOVERY:
+		return !!(caps & VSEC_CAP_DISCOVERY);
 	default:
 		return false;
 	}
@@ -138,6 +143,8 @@ static bool vsec_driver_present(int cap_id)
 		return IS_ENABLED(CONFIG_INTEL_SDSI);
 	case VSEC_CAP_TPMI:
 		return IS_ENABLED(CONFIG_INTEL_TPMI);
+	case VSEC_CAP_DISCOVERY:
+		return IS_ENABLED(CONFIG_INTEL_PMT_DISCOVERY);
 	default:
 		return false;
 	}
@@ -392,6 +399,9 @@ static int get_cap_id(u32 header_id, unsigned long *cap_id)
 	case VSEC_ID_TPMI:
 		*cap_id = ilog2(VSEC_CAP_TPMI);
 		break;
+	case VSEC_ID_DISCOVERY:
+		*cap_id = ilog2(VSEC_CAP_DISCOVERY);
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -681,14 +691,26 @@ static const struct intel_vsec_platform_info mtl_info = {
 	.caps = VSEC_CAP_TELEMETRY,
 };
 
+static const struct vsec_feature_dependency oobmsm_deps[] = {
+	{
+		.feature = VSEC_CAP_TELEMETRY,
+		.supplier_bitmap = VSEC_CAP_DISCOVERY,
+	},
+};
+
 /* OOBMSM info */
 static const struct intel_vsec_platform_info oobmsm_info = {
-	.caps = VSEC_CAP_TELEMETRY | VSEC_CAP_SDSI | VSEC_CAP_TPMI,
+	.caps = VSEC_CAP_TELEMETRY | VSEC_CAP_SDSI | VSEC_CAP_TPMI |
+		VSEC_CAP_DISCOVERY,
+	.deps = oobmsm_deps,
+	.num_deps = ARRAY_SIZE(oobmsm_deps),
 };
 
 /* DMR OOBMSM info */
 static const struct intel_vsec_platform_info dmr_oobmsm_info = {
-	.caps = VSEC_CAP_TELEMETRY | VSEC_CAP_TPMI,
+	.caps = VSEC_CAP_TELEMETRY | VSEC_CAP_TPMI | VSEC_CAP_DISCOVERY,
+	.deps = oobmsm_deps,
+	.num_deps = ARRAY_SIZE(oobmsm_deps),
 };
 
 /* TGL info */
diff --git a/include/linux/intel_vsec.h b/include/linux/intel_vsec.h
index 71067afaca99..a07796d7d43b 100644
--- a/include/linux/intel_vsec.h
+++ b/include/linux/intel_vsec.h
@@ -16,7 +16,8 @@
 #define VSEC_CAP_CRASHLOG	BIT(3)
 #define VSEC_CAP_SDSI		BIT(4)
 #define VSEC_CAP_TPMI		BIT(5)
-#define VSEC_FEATURE_COUNT	6
+#define VSEC_CAP_DISCOVERY	BIT(6)
+#define VSEC_FEATURE_COUNT	7
 
 /* Intel DVSEC offsets */
 #define INTEL_DVSEC_ENTRIES		0xA
@@ -33,6 +34,7 @@ enum intel_vsec_id {
 	VSEC_ID_TELEMETRY	= 2,
 	VSEC_ID_WATCHER		= 3,
 	VSEC_ID_CRASHLOG	= 4,
+	VSEC_ID_DISCOVERY	= 12,
 	VSEC_ID_SDSI		= 65,
 	VSEC_ID_TPMI		= 66,
 };
-- 
2.43.0


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

* [PATCH V3 08/15] platform/x86/intel/pmt: Add PMT Discovery driver
  2025-07-03  2:28 [PATCH V3 00/15] Intel VSEC/PMT: Introduce Discovery Driver David E. Box
                   ` (6 preceding siblings ...)
  2025-07-03  2:28 ` [PATCH V3 07/15] platform/x86/intel/vsec: Add new Discovery feature David E. Box
@ 2025-07-03  2:28 ` David E. Box
  2025-07-03  2:28 ` [PATCH V3 09/15] docs: Add ABI documentation for intel_pmt feature directories David E. Box
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: David E. Box @ 2025-07-03  2:28 UTC (permalink / raw)
  To: linux-kernel, platform-driver-x86, david.e.box,
	srinivas.pandruvada, andriy.shevchenko, ilpo.jarvinen, tony.luck,
	xi.pardee
  Cc: hdegoede

This patch introduces a new driver to enumerate and expose Intel Platform
Monitoring Technology (PMT) capabilities via a simple discovery mechanism.
The PMT Discovery driver parses hardware-provided discovery tables from
Intel Out of Band Management Services Modules (OOBMSM) and extracts feature
information for various providers (such as TPMI, Telemetry, Crash Log,
etc). This unified interface simplifies the process of determining which
manageability and telemetry features are supported by a given platform.

This new feature is described in the Intel Platform Monitoring Technology
3.0 specification, section 6.6 Capability.

Key changes and additions:

New file drivers/platform/x86/intel/pmt/discovery.c:
  – Implements the discovery logic to map the discovery resource, read
    the feature discovery table, and validate feature parameters.
New file drivers/platform/x86/intel/pmt/features.c:
  – Defines feature names, layouts, and associated capability masks.
  – Provides a mapping between raw hardware attributes and sysfs
    representations for easier integration with user-space tools.
New header include/linux/intel_pmt_features.h:
  – Declares constants, masks, and feature identifiers used across the
    PMT framework.
Sysfs integration:
  – Feature attributes are exposed under /sys/class/intel_pmt.
  – Each device is represented by a subfolder within the intel_pmt class,
    named using its DBDF (Domain:Bus:Device.Function), e.g.:
        features-0000:00:03.1
  – Example directory layout for a device:

    /sys/class/intel_pmt/features-0000:00:03.1/
    ├── accelerator_telemetry
    ├── crash_log
    ├── per_core_environment_telemetry
    ├── per_core_performance_telemetry
    ├── per_rmid_energy_telemetry
    ├── per_rmid_perf_telemetry
    ├── tpmi_control
    ├── tracing
    └── uncore_telemetry

By exposing PMT feature details through sysfs and integrating with the
existing PMT class, this driver paves the way for more streamlined
integration of PMT-based manageability and telemetry tools.

Link: https://www.intel.com/content/www/us/en/content-details/710389/intel-platform-monitoring-technology-intel-pmt-external-specification.html
Signed-off-by: David E. Box <david.e.box@linux.intel.com>
---

Changes in v3:
  - No changes

Changes in v2:
  - Add comment spelling out RMID
  - Remove extra parens around several uses of PTR_ERR()
  - Add PMT_ACCESS_TYPE_RSVD for magic number 0x7
  - In pmt_feature_discovery() clarify zero-init of disc_tbl is for false
    positive compiler warning.
  - In features.c fix several spelling errors, use snake case
    consistently for all capability names, and spell out "telemetry".

 drivers/platform/x86/intel/pmt/Kconfig     |  12 +
 drivers/platform/x86/intel/pmt/Makefile    |   2 +
 drivers/platform/x86/intel/pmt/class.c     |  35 +-
 drivers/platform/x86/intel/pmt/class.h     |   2 +
 drivers/platform/x86/intel/pmt/discovery.c | 602 +++++++++++++++++++++
 drivers/platform/x86/intel/pmt/features.c  | 205 +++++++
 include/linux/intel_pmt_features.h         | 157 ++++++
 7 files changed, 1013 insertions(+), 2 deletions(-)
 create mode 100644 drivers/platform/x86/intel/pmt/discovery.c
 create mode 100644 drivers/platform/x86/intel/pmt/features.c
 create mode 100644 include/linux/intel_pmt_features.h

diff --git a/drivers/platform/x86/intel/pmt/Kconfig b/drivers/platform/x86/intel/pmt/Kconfig
index e916fc966221..0ad91b5112e9 100644
--- a/drivers/platform/x86/intel/pmt/Kconfig
+++ b/drivers/platform/x86/intel/pmt/Kconfig
@@ -38,3 +38,15 @@ config INTEL_PMT_CRASHLOG
 
 	  To compile this driver as a module, choose M here: the module
 	  will be called intel_pmt_crashlog.
+
+config INTEL_PMT_DISCOVERY
+	tristate "Intel Platform Monitoring Technology (PMT) Discovery driver"
+	depends on INTEL_VSEC
+	select INTEL_PMT_CLASS
+	help
+	  The Intel Platform Monitoring Technology (PMT) discovery driver provides
+	  access to details about the various PMT features and feature specific
+	  attributes.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called pmt_discovery.
diff --git a/drivers/platform/x86/intel/pmt/Makefile b/drivers/platform/x86/intel/pmt/Makefile
index 279e158c7c23..8aed7e1592e4 100644
--- a/drivers/platform/x86/intel/pmt/Makefile
+++ b/drivers/platform/x86/intel/pmt/Makefile
@@ -10,3 +10,5 @@ obj-$(CONFIG_INTEL_PMT_TELEMETRY)	+= pmt_telemetry.o
 pmt_telemetry-y				:= telemetry.o
 obj-$(CONFIG_INTEL_PMT_CRASHLOG)	+= pmt_crashlog.o
 pmt_crashlog-y				:= crashlog.o
+obj-$(CONFIG_INTEL_PMT_DISCOVERY)	+= pmt_discovery.o
+pmt_discovery-y				:= discovery.o features.o
diff --git a/drivers/platform/x86/intel/pmt/class.c b/drivers/platform/x86/intel/pmt/class.c
index 7233b654bbad..a806a81ece52 100644
--- a/drivers/platform/x86/intel/pmt/class.c
+++ b/drivers/platform/x86/intel/pmt/class.c
@@ -9,11 +9,13 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/log2.h>
 #include <linux/intel_vsec.h>
 #include <linux/io-64-nonatomic-lo-hi.h>
 #include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/pci.h>
+#include <linux/sysfs.h>
 
 #include "class.h"
 
@@ -166,12 +168,41 @@ static struct attribute *intel_pmt_attrs[] = {
 	&dev_attr_offset.attr,
 	NULL
 };
-ATTRIBUTE_GROUPS(intel_pmt);
 
-static struct class intel_pmt_class = {
+static umode_t intel_pmt_attr_visible(struct kobject *kobj,
+				      struct attribute *attr, int n)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct auxiliary_device *auxdev = to_auxiliary_dev(dev->parent);
+	struct intel_vsec_device *ivdev = auxdev_to_ivdev(auxdev);
+
+	/*
+	 * Place the discovery features folder in /sys/class/intel_pmt, but
+	 * exclude the common attributes as they are not applicable.
+	 */
+	if (ivdev->cap_id == ilog2(VSEC_CAP_DISCOVERY))
+		return 0;
+
+	return attr->mode;
+}
+
+static bool intel_pmt_group_visible(struct kobject *kobj)
+{
+	return true;
+}
+DEFINE_SYSFS_GROUP_VISIBLE(intel_pmt);
+
+static const struct attribute_group intel_pmt_group = {
+	.attrs = intel_pmt_attrs,
+	.is_visible = SYSFS_GROUP_VISIBLE(intel_pmt),
+};
+__ATTRIBUTE_GROUPS(intel_pmt);
+
+struct class intel_pmt_class = {
 	.name = "intel_pmt",
 	.dev_groups = intel_pmt_groups,
 };
+EXPORT_SYMBOL_GPL(intel_pmt_class);
 
 static int intel_pmt_populate_entry(struct intel_pmt_entry *entry,
 				    struct intel_vsec_device *ivdev,
diff --git a/drivers/platform/x86/intel/pmt/class.h b/drivers/platform/x86/intel/pmt/class.h
index b2006d57779d..39c32357ee2c 100644
--- a/drivers/platform/x86/intel/pmt/class.h
+++ b/drivers/platform/x86/intel/pmt/class.h
@@ -20,6 +20,7 @@
 #define GET_ADDRESS(v)		((v) & GENMASK(31, 3))
 
 struct pci_dev;
+extern struct class intel_pmt_class;
 
 struct telem_endpoint {
 	struct pci_dev		*pcidev;
@@ -48,6 +49,7 @@ struct intel_pmt_entry {
 	unsigned long		base_addr;
 	size_t			size;
 	u32			guid;
+	u32			num_rmids; /* Number of Resource Monitoring IDs */
 	int			devid;
 };
 
diff --git a/drivers/platform/x86/intel/pmt/discovery.c b/drivers/platform/x86/intel/pmt/discovery.c
new file mode 100644
index 000000000000..4b4fa3137ad2
--- /dev/null
+++ b/drivers/platform/x86/intel/pmt/discovery.c
@@ -0,0 +1,602 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Intel Platform Monitory Technology Discovery driver
+ *
+ * Copyright (c) 2025, Intel Corporation.
+ * All Rights Reserved.
+ */
+
+#include <linux/auxiliary_bus.h>
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/bug.h>
+#include <linux/cleanup.h>
+#include <linux/container_of.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/kdev_t.h>
+#include <linux/kobject.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/overflow.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/string_choices.h>
+#include <linux/sysfs.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+
+#include <linux/intel_pmt_features.h>
+#include <linux/intel_vsec.h>
+
+#include "class.h"
+
+#define MAX_FEATURE_VERSION	0
+#define DT_TBIR			GENMASK(2, 0)
+#define FEAT_ATTR_SIZE(x)	((x) * sizeof(u32))
+#define PMT_GUID_SIZE(x)	((x) * sizeof(u32))
+#define PMT_ACCESS_TYPE_RSVD	0xF
+#define SKIP_FEATURE		1
+
+struct feature_discovery_table {
+	u32	access_type:4;
+	u32	version:8;
+	u32	size:16;
+	u32	reserved:4;
+	u32	id;
+	u32	offset;
+	u32	reserved2;
+};
+
+/* Common feature table header */
+struct feature_header {
+	u32	attr_size:8;
+	u32	num_guids:8;
+	u32	reserved:16;
+};
+
+/* Feature attribute fields */
+struct caps {
+	u32		caps;
+};
+
+struct command {
+	u32		max_stream_size:16;
+	u32		max_command_size:16;
+};
+
+struct watcher {
+	u32		reserved:21;
+	u32		period:11;
+	struct command	command;
+};
+
+struct rmid {
+	u32		num_rmids:16;	/* Number of Resource Monitoring IDs */
+	u32		reserved:16;
+	struct watcher	watcher;
+};
+
+struct feature_table {
+	struct feature_header	header;
+	struct caps		caps;
+	union {
+		struct command command;
+		struct watcher watcher;
+		struct rmid rmid;
+	};
+	u32			*guids;
+};
+
+/* For backreference in struct feature */
+struct pmt_features_priv;
+
+struct feature {
+	struct feature_table		table;
+	struct kobject			kobj;
+	struct pmt_features_priv	*priv;
+	struct list_head		list;
+	const struct attribute_group	*attr_group;
+	enum pmt_feature_id		id;
+};
+
+struct pmt_features_priv {
+	struct device		*parent;
+	struct device		*dev;
+	int			count;
+	u32			mask;
+	struct feature		feature[];
+};
+
+static LIST_HEAD(pmt_feature_list);
+static DEFINE_MUTEX(feature_list_lock);
+
+#define to_pmt_feature(x) container_of(x, struct feature, kobj)
+static void pmt_feature_release(struct kobject *kobj)
+{
+}
+
+static ssize_t caps_show(struct kobject *kobj, struct kobj_attribute *attr,
+			 char *buf)
+{
+	struct feature *feature = to_pmt_feature(kobj);
+	struct pmt_cap **pmt_caps;
+	u32 caps = feature->table.caps.caps;
+	ssize_t ret = 0;
+
+	switch (feature->id) {
+	case FEATURE_PER_CORE_PERF_TELEM:
+		pmt_caps = pmt_caps_pcpt;
+		break;
+	case FEATURE_PER_CORE_ENV_TELEM:
+		pmt_caps = pmt_caps_pcet;
+		break;
+	case FEATURE_PER_RMID_PERF_TELEM:
+		pmt_caps = pmt_caps_rmid_perf;
+		break;
+	case FEATURE_ACCEL_TELEM:
+		pmt_caps = pmt_caps_accel;
+		break;
+	case FEATURE_UNCORE_TELEM:
+		pmt_caps = pmt_caps_uncore;
+		break;
+	case FEATURE_CRASH_LOG:
+		pmt_caps = pmt_caps_crashlog;
+		break;
+	case FEATURE_PETE_LOG:
+		pmt_caps = pmt_caps_pete;
+		break;
+	case FEATURE_TPMI_CTRL:
+		pmt_caps = pmt_caps_tpmi;
+		break;
+	case FEATURE_TRACING:
+		pmt_caps = pmt_caps_tracing;
+		break;
+	case FEATURE_PER_RMID_ENERGY_TELEM:
+		pmt_caps = pmt_caps_rmid_energy;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	while (*pmt_caps) {
+		struct pmt_cap *pmt_cap = *pmt_caps;
+
+		while (pmt_cap->name) {
+			ret += sysfs_emit_at(buf, ret, "%-40s Available: %s\n", pmt_cap->name,
+					     str_yes_no(pmt_cap->mask & caps));
+			pmt_cap++;
+		}
+		pmt_caps++;
+	}
+
+	return ret;
+}
+static struct kobj_attribute caps_attribute = __ATTR_RO(caps);
+
+static struct watcher *get_watcher(struct feature *feature)
+{
+	switch (feature_layout[feature->id]) {
+	case LAYOUT_RMID:
+		return &feature->table.rmid.watcher;
+	case LAYOUT_WATCHER:
+		return &feature->table.watcher;
+	default:
+		return ERR_PTR(-EINVAL);
+	}
+}
+
+static struct command *get_command(struct feature *feature)
+{
+	switch (feature_layout[feature->id]) {
+	case LAYOUT_RMID:
+		return &feature->table.rmid.watcher.command;
+	case LAYOUT_WATCHER:
+		return &feature->table.watcher.command;
+	case LAYOUT_COMMAND:
+		return &feature->table.command;
+	default:
+		return ERR_PTR(-EINVAL);
+	}
+}
+
+static ssize_t num_rmids_show(struct kobject *kobj,
+			      struct kobj_attribute *attr, char *buf)
+{
+	struct feature *feature = to_pmt_feature(kobj);
+
+	return sysfs_emit(buf, "%u\n", feature->table.rmid.num_rmids);
+}
+static struct kobj_attribute num_rmids_attribute = __ATTR_RO(num_rmids);
+
+static ssize_t min_watcher_period_ms_show(struct kobject *kobj,
+					  struct kobj_attribute *attr, char *buf)
+{
+	struct feature *feature = to_pmt_feature(kobj);
+	struct watcher *watcher = get_watcher(feature);
+
+	if (IS_ERR(watcher))
+		return PTR_ERR(watcher);
+
+	return sysfs_emit(buf, "%u\n", watcher->period);
+}
+static struct kobj_attribute min_watcher_period_ms_attribute =
+	__ATTR_RO(min_watcher_period_ms);
+
+static ssize_t max_stream_size_show(struct kobject *kobj,
+				    struct kobj_attribute *attr, char *buf)
+{
+	struct feature *feature = to_pmt_feature(kobj);
+	struct command *command = get_command(feature);
+
+	if (IS_ERR(command))
+		return PTR_ERR(command);
+
+	return sysfs_emit(buf, "%u\n", command->max_stream_size);
+}
+static struct kobj_attribute max_stream_size_attribute =
+	__ATTR_RO(max_stream_size);
+
+static ssize_t max_command_size_show(struct kobject *kobj,
+				     struct kobj_attribute *attr, char *buf)
+{
+	struct feature *feature = to_pmt_feature(kobj);
+	struct command *command = get_command(feature);
+
+	if (IS_ERR(command))
+		return PTR_ERR(command);
+
+	return sysfs_emit(buf, "%u\n", command->max_command_size);
+}
+static struct kobj_attribute max_command_size_attribute =
+	__ATTR_RO(max_command_size);
+
+static ssize_t guids_show(struct kobject *kobj, struct kobj_attribute *attr,
+			  char *buf)
+{
+	struct feature *feature = to_pmt_feature(kobj);
+	int i, count = 0;
+
+	for (i = 0; i < feature->table.header.num_guids; i++)
+		count += sysfs_emit_at(buf, count, "0x%x\n",
+				       feature->table.guids[i]);
+
+	return count;
+}
+static struct kobj_attribute guids_attribute = __ATTR_RO(guids);
+
+static struct attribute *pmt_feature_rmid_attrs[] = {
+	&caps_attribute.attr,
+	&num_rmids_attribute.attr,
+	&min_watcher_period_ms_attribute.attr,
+	&max_stream_size_attribute.attr,
+	&max_command_size_attribute.attr,
+	&guids_attribute.attr,
+	NULL
+};
+ATTRIBUTE_GROUPS(pmt_feature_rmid);
+
+static const struct kobj_type pmt_feature_rmid_ktype = {
+	.sysfs_ops = &kobj_sysfs_ops,
+	.release = pmt_feature_release,
+	.default_groups = pmt_feature_rmid_groups,
+};
+
+static struct attribute *pmt_feature_watcher_attrs[] = {
+	&caps_attribute.attr,
+	&min_watcher_period_ms_attribute.attr,
+	&max_stream_size_attribute.attr,
+	&max_command_size_attribute.attr,
+	&guids_attribute.attr,
+	NULL
+};
+ATTRIBUTE_GROUPS(pmt_feature_watcher);
+
+static const struct kobj_type pmt_feature_watcher_ktype = {
+	.sysfs_ops = &kobj_sysfs_ops,
+	.release = pmt_feature_release,
+	.default_groups = pmt_feature_watcher_groups,
+};
+
+static struct attribute *pmt_feature_command_attrs[] = {
+	&caps_attribute.attr,
+	&max_stream_size_attribute.attr,
+	&max_command_size_attribute.attr,
+	&guids_attribute.attr,
+	NULL
+};
+ATTRIBUTE_GROUPS(pmt_feature_command);
+
+static const struct kobj_type pmt_feature_command_ktype = {
+	.sysfs_ops = &kobj_sysfs_ops,
+	.release = pmt_feature_release,
+	.default_groups = pmt_feature_command_groups,
+};
+
+static struct attribute *pmt_feature_guids_attrs[] = {
+	&caps_attribute.attr,
+	&guids_attribute.attr,
+	NULL
+};
+ATTRIBUTE_GROUPS(pmt_feature_guids);
+
+static const struct kobj_type pmt_feature_guids_ktype = {
+	.sysfs_ops = &kobj_sysfs_ops,
+	.release = pmt_feature_release,
+	.default_groups = pmt_feature_guids_groups,
+};
+
+static int
+pmt_feature_get_disc_table(struct pmt_features_priv *priv,
+			   struct resource *disc_res,
+			   struct feature_discovery_table *disc_tbl)
+{
+	void __iomem *disc_base;
+
+	disc_base = devm_ioremap_resource(priv->dev, disc_res);
+	if (IS_ERR(disc_base))
+		return PTR_ERR(disc_base);
+
+	memcpy_fromio(disc_tbl, disc_base, sizeof(*disc_tbl));
+
+	devm_iounmap(priv->dev, disc_base);
+
+	if (priv->mask & BIT(disc_tbl->id))
+		return dev_err_probe(priv->dev, -EINVAL, "Duplicate feature: %s\n",
+				     pmt_feature_names[disc_tbl->id]);
+
+	/*
+	 * Some devices may expose non-functioning entries that are
+	 * reserved for future use. They have zero size. Do not fail
+	 * probe for these. Just ignore them.
+	 */
+	if (disc_tbl->size == 0 || disc_tbl->access_type == PMT_ACCESS_TYPE_RSVD)
+		return SKIP_FEATURE;
+
+	if (disc_tbl->version > MAX_FEATURE_VERSION)
+		return SKIP_FEATURE;
+
+	if (!pmt_feature_id_is_valid(disc_tbl->id))
+		return SKIP_FEATURE;
+
+	priv->mask |= BIT(disc_tbl->id);
+
+	return 0;
+}
+
+static int
+pmt_feature_get_feature_table(struct pmt_features_priv *priv,
+			      struct feature *feature,
+			      struct feature_discovery_table *disc_tbl,
+			      struct resource *disc_res)
+{
+	struct feature_table *feat_tbl = &feature->table;
+	struct feature_header *header;
+	struct resource res = {};
+	resource_size_t res_size;
+	void __iomem *feat_base, *feat_offset;
+	void *tbl_offset;
+	size_t size;
+	u32 *guids;
+	u8 tbir;
+
+	tbir = FIELD_GET(DT_TBIR, disc_tbl->offset);
+
+	switch (disc_tbl->access_type) {
+	case ACCESS_LOCAL:
+		if (tbir)
+			return dev_err_probe(priv->dev, -EINVAL,
+				"Unsupported BAR index %u for access type %u\n",
+				tbir, disc_tbl->access_type);
+
+
+		/*
+		 * For access_type LOCAL, the base address is as follows:
+		 * base address = end of discovery region + base offset + 1
+		 */
+		res = DEFINE_RES_MEM(disc_res->end + disc_tbl->offset + 1,
+				     disc_tbl->size * sizeof(u32));
+		break;
+
+	default:
+		return dev_err_probe(priv->dev, -EINVAL, "Unrecognized access_type %u\n",
+				     disc_tbl->access_type);
+	}
+
+	feature->id = disc_tbl->id;
+
+	/* Get the feature table */
+	feat_base = devm_ioremap_resource(priv->dev, &res);
+	if (IS_ERR(feat_base))
+		return PTR_ERR(feat_base);
+
+	feat_offset = feat_base;
+	tbl_offset = feat_tbl;
+
+	/* Get the header */
+	header = &feat_tbl->header;
+	memcpy_fromio(header, feat_offset, sizeof(*header));
+
+	/* Validate fields fit within mapped resource */
+	size = sizeof(*header) + FEAT_ATTR_SIZE(header->attr_size) +
+	       PMT_GUID_SIZE(header->num_guids);
+	res_size = resource_size(&res);
+	if (WARN(size > res_size, "Bad table size %ld > %pa", size, &res_size))
+		return -EINVAL;
+
+	/* Get the feature attributes, including capability fields */
+	tbl_offset += sizeof(*header);
+	feat_offset += sizeof(*header);
+
+	memcpy_fromio(tbl_offset, feat_offset, FEAT_ATTR_SIZE(header->attr_size));
+
+	/* Finally, get the guids */
+	guids = devm_kmalloc(priv->dev, PMT_GUID_SIZE(header->num_guids), GFP_KERNEL);
+	if (!guids)
+		return -ENOMEM;
+
+	feat_offset += FEAT_ATTR_SIZE(header->attr_size);
+
+	memcpy_fromio(guids, feat_offset, PMT_GUID_SIZE(header->num_guids));
+
+	feat_tbl->guids = guids;
+
+	devm_iounmap(priv->dev, feat_base);
+
+	return 0;
+}
+
+static void pmt_features_add_feat(struct feature *feature)
+{
+	guard(mutex)(&feature_list_lock);
+	list_add(&feature->list, &pmt_feature_list);
+}
+
+static void pmt_features_remove_feat(struct feature *feature)
+{
+	guard(mutex)(&feature_list_lock);
+	list_del(&feature->list);
+}
+
+/* Get the discovery table and use it to get the feature table */
+static int pmt_features_discovery(struct pmt_features_priv *priv,
+				  struct feature *feature,
+				  struct intel_vsec_device *ivdev,
+				  int idx)
+{
+	struct feature_discovery_table disc_tbl = {}; /* Avoid false warning */
+	struct resource *disc_res = &ivdev->resource[idx];
+	const struct kobj_type *ktype;
+	int ret;
+
+	ret = pmt_feature_get_disc_table(priv, disc_res, &disc_tbl);
+	if (ret)
+		return ret;
+
+	ret = pmt_feature_get_feature_table(priv, feature, &disc_tbl, disc_res);
+	if (ret)
+		return ret;
+
+	switch (feature_layout[feature->id]) {
+	case LAYOUT_RMID:
+		ktype = &pmt_feature_rmid_ktype;
+		feature->attr_group = &pmt_feature_rmid_group;
+		break;
+	case LAYOUT_WATCHER:
+		ktype = &pmt_feature_watcher_ktype;
+		feature->attr_group = &pmt_feature_watcher_group;
+		break;
+	case LAYOUT_COMMAND:
+		ktype = &pmt_feature_command_ktype;
+		feature->attr_group = &pmt_feature_command_group;
+		break;
+	case LAYOUT_CAPS_ONLY:
+		ktype = &pmt_feature_guids_ktype;
+		feature->attr_group = &pmt_feature_guids_group;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	ret = kobject_init_and_add(&feature->kobj, ktype, &priv->dev->kobj,
+				   pmt_feature_names[feature->id]);
+	if (ret)
+		return ret;
+
+	kobject_uevent(&feature->kobj, KOBJ_ADD);
+	pmt_features_add_feat(feature);
+
+	return 0;
+}
+
+static void pmt_features_remove(struct auxiliary_device *auxdev)
+{
+	struct pmt_features_priv *priv = auxiliary_get_drvdata(auxdev);
+	int i;
+
+	for (i = 0; i < priv->count; i++) {
+		struct feature *feature = &priv->feature[i];
+
+		pmt_features_remove_feat(feature);
+		sysfs_remove_group(&feature->kobj, feature->attr_group);
+		kobject_put(&feature->kobj);
+	}
+
+	device_unregister(priv->dev);
+}
+
+static int pmt_features_probe(struct auxiliary_device *auxdev, const struct auxiliary_device_id *id)
+{
+	struct intel_vsec_device *ivdev = auxdev_to_ivdev(auxdev);
+	struct pmt_features_priv *priv;
+	size_t size;
+	int ret, i;
+
+	size = struct_size(priv, feature, ivdev->num_resources);
+	priv = devm_kzalloc(&auxdev->dev, size, GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->parent = &ivdev->pcidev->dev;
+	auxiliary_set_drvdata(auxdev, priv);
+
+	priv->dev = device_create(&intel_pmt_class, &auxdev->dev, MKDEV(0, 0), priv,
+				  "%s-%s", "features", dev_name(priv->parent));
+	if (IS_ERR(priv->dev))
+		return dev_err_probe(priv->dev, PTR_ERR(priv->dev),
+				     "Could not create %s-%s device node\n",
+				     "features", dev_name(priv->dev));
+
+	/* Initialize each feature */
+	for (i = 0; i < ivdev->num_resources; i++) {
+		struct feature *feature = &priv->feature[priv->count];
+
+		ret = pmt_features_discovery(priv, feature, ivdev, i);
+		if (ret == SKIP_FEATURE)
+			continue;
+		if (ret != 0)
+			goto abort_probe;
+
+		feature->priv = priv;
+		priv->count++;
+	}
+
+	return 0;
+
+abort_probe:
+	/*
+	 * Only fully initialized features are tracked in priv->count, which is
+	 * incremented only after a feature is completely set up (i.e., after
+	 * discovery and sysfs registration). If feature initialization fails,
+	 * the failing feature's state is local and does not require rollback.
+	 *
+	 * Therefore, on error, we can safely call the driver's remove() routine
+	 * pmt_features_remove() to clean up only those features that were
+	 * fully initialized and counted. All other resources are device-managed
+	 * and will be cleaned up automatically during device_unregister().
+	 */
+	pmt_features_remove(auxdev);
+
+	return ret;
+}
+
+static const struct auxiliary_device_id pmt_features_id_table[] = {
+	{ .name = "intel_vsec.discovery" },
+	{}
+};
+MODULE_DEVICE_TABLE(auxiliary, pmt_features_id_table);
+
+static struct auxiliary_driver pmt_features_aux_driver = {
+	.id_table	= pmt_features_id_table,
+	.remove		= pmt_features_remove,
+	.probe		= pmt_features_probe,
+};
+module_auxiliary_driver(pmt_features_aux_driver);
+
+MODULE_AUTHOR("David E. Box <david.e.box@linux.intel.com>");
+MODULE_DESCRIPTION("Intel PMT Discovery driver");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("INTEL_PMT");
diff --git a/drivers/platform/x86/intel/pmt/features.c b/drivers/platform/x86/intel/pmt/features.c
new file mode 100644
index 000000000000..8a39cddc75c8
--- /dev/null
+++ b/drivers/platform/x86/intel/pmt/features.c
@@ -0,0 +1,205 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2025, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * Author: "David E. Box" <david.e.box@linux.intel.com>
+ */
+
+#include <linux/export.h>
+#include <linux/types.h>
+
+#include <linux/intel_pmt_features.h>
+
+const char * const pmt_feature_names[] = {
+	[FEATURE_PER_CORE_PERF_TELEM]	= "per_core_performance_telemetry",
+	[FEATURE_PER_CORE_ENV_TELEM]	= "per_core_environment_telemetry",
+	[FEATURE_PER_RMID_PERF_TELEM]	= "per_rmid_perf_telemetry",
+	[FEATURE_ACCEL_TELEM]		= "accelerator_telemetry",
+	[FEATURE_UNCORE_TELEM]		= "uncore_telemetry",
+	[FEATURE_CRASH_LOG]		= "crash_log",
+	[FEATURE_PETE_LOG]		= "pete_log",
+	[FEATURE_TPMI_CTRL]		= "tpmi_control",
+	[FEATURE_TRACING]		= "tracing",
+	[FEATURE_PER_RMID_ENERGY_TELEM]	= "per_rmid_energy_telemetry",
+};
+EXPORT_SYMBOL_NS_GPL(pmt_feature_names, "INTEL_PMT_DISCOVERY");
+
+enum feature_layout feature_layout[] = {
+	[FEATURE_PER_CORE_PERF_TELEM]	= LAYOUT_WATCHER,
+	[FEATURE_PER_CORE_ENV_TELEM]	= LAYOUT_WATCHER,
+	[FEATURE_PER_RMID_PERF_TELEM]	= LAYOUT_RMID,
+	[FEATURE_ACCEL_TELEM]		= LAYOUT_WATCHER,
+	[FEATURE_UNCORE_TELEM]		= LAYOUT_WATCHER,
+	[FEATURE_CRASH_LOG]		= LAYOUT_COMMAND,
+	[FEATURE_PETE_LOG]		= LAYOUT_COMMAND,
+	[FEATURE_TPMI_CTRL]		= LAYOUT_CAPS_ONLY,
+	[FEATURE_TRACING]		= LAYOUT_CAPS_ONLY,
+	[FEATURE_PER_RMID_ENERGY_TELEM]	= LAYOUT_RMID,
+};
+
+struct pmt_cap pmt_cap_common[] = {
+	{PMT_CAP_TELEM,		"telemetry"},
+	{PMT_CAP_WATCHER,	"watcher"},
+	{PMT_CAP_CRASHLOG,	"crashlog"},
+	{PMT_CAP_STREAMING,	"streaming"},
+	{PMT_CAP_THRESHOLD,	"threshold"},
+	{PMT_CAP_WINDOW,	"window"},
+	{PMT_CAP_CONFIG,	"config"},
+	{PMT_CAP_TRACING,	"tracing"},
+	{PMT_CAP_INBAND,	"inband"},
+	{PMT_CAP_OOB,		"oob"},
+	{PMT_CAP_SECURED_CHAN,	"secure_chan"},
+	{PMT_CAP_PMT_SP,	"pmt_sp"},
+	{PMT_CAP_PMT_SP_POLICY,	"pmt_sp_policy"},
+	{}
+};
+
+struct pmt_cap pmt_cap_pcpt[] = {
+	{PMT_CAP_PCPT_CORE_PERF,	"core_performance"},
+	{PMT_CAP_PCPT_CORE_C0_RES,	"core_c0_residency"},
+	{PMT_CAP_PCPT_CORE_ACTIVITY,	"core_activity"},
+	{PMT_CAP_PCPT_CACHE_PERF,	"cache_performance"},
+	{PMT_CAP_PCPT_QUALITY_TELEM,	"quality_telemetry"},
+	{}
+};
+
+struct pmt_cap *pmt_caps_pcpt[] = {
+	pmt_cap_common,
+	pmt_cap_pcpt,
+	NULL
+};
+
+struct pmt_cap pmt_cap_pcet[] = {
+	{PMT_CAP_PCET_WORKPOINT_HIST,	"workpoint_histogram"},
+	{PMT_CAP_PCET_CORE_CURR_TEMP,	"core_current_temp"},
+	{PMT_CAP_PCET_CORE_INST_RES,	"core_inst_residency"},
+	{PMT_CAP_PCET_QUALITY_TELEM,	"quality_telemetry"},
+	{PMT_CAP_PCET_CORE_CDYN_LVL,	"core_cdyn_level"},
+	{PMT_CAP_PCET_CORE_STRESS_LVL,	"core_stress_level"},
+	{PMT_CAP_PCET_CORE_DAS,		"core_digital_aging_sensor"},
+	{PMT_CAP_PCET_FIVR_HEALTH,	"fivr_health"},
+	{PMT_CAP_PCET_ENERGY,		"energy"},
+	{PMT_CAP_PCET_PEM_STATUS,	"pem_status"},
+	{PMT_CAP_PCET_CORE_C_STATE,	"core_c_state"},
+	{}
+};
+
+struct pmt_cap *pmt_caps_pcet[] = {
+	pmt_cap_common,
+	pmt_cap_pcet,
+	NULL
+};
+
+struct pmt_cap pmt_cap_rmid_perf[] = {
+	{PMT_CAP_RMID_CORES_PERF,	"core_performance"},
+	{PMT_CAP_RMID_CACHE_PERF,	"cache_performance"},
+	{PMT_CAP_RMID_PERF_QUAL,	"performance_quality"},
+	{}
+};
+
+struct pmt_cap *pmt_caps_rmid_perf[] = {
+	pmt_cap_common,
+	pmt_cap_rmid_perf,
+	NULL
+};
+
+struct pmt_cap pmt_cap_accel[] = {
+	{PMT_CAP_ACCEL_CPM_TELEM,	"content_processing_module"},
+	{PMT_CAP_ACCEL_TIP_TELEM,	"content_turbo_ip"},
+	{}
+};
+
+struct pmt_cap *pmt_caps_accel[] = {
+	pmt_cap_common,
+	pmt_cap_accel,
+	NULL
+};
+
+struct pmt_cap pmt_cap_uncore[] = {
+	{PMT_CAP_UNCORE_IO_CA_TELEM,	"io_ca"},
+	{PMT_CAP_UNCORE_RMID_TELEM,	"rmid"},
+	{PMT_CAP_UNCORE_D2D_ULA_TELEM,	"d2d_ula"},
+	{PMT_CAP_UNCORE_PKGC_TELEM,	"package_c"},
+	{}
+};
+
+struct pmt_cap *pmt_caps_uncore[] = {
+	pmt_cap_common,
+	pmt_cap_uncore,
+	NULL
+};
+
+struct pmt_cap pmt_cap_crashlog[] = {
+	{PMT_CAP_CRASHLOG_MAN_TRIG,	"manual_trigger"},
+	{PMT_CAP_CRASHLOG_CORE,		"core"},
+	{PMT_CAP_CRASHLOG_UNCORE,	"uncore"},
+	{PMT_CAP_CRASHLOG_TOR,		"tor"},
+	{PMT_CAP_CRASHLOG_S3M,		"s3m"},
+	{PMT_CAP_CRASHLOG_PERSISTENCY,	"persistency"},
+	{PMT_CAP_CRASHLOG_CLIP_GPIO,	"crashlog_in_progress"},
+	{PMT_CAP_CRASHLOG_PRE_RESET,	"pre_reset_extraction"},
+	{PMT_CAP_CRASHLOG_POST_RESET,	"post_reset_extraction"},
+	{}
+};
+
+struct pmt_cap *pmt_caps_crashlog[] = {
+	pmt_cap_common,
+	pmt_cap_crashlog,
+	NULL
+};
+
+struct pmt_cap pmt_cap_pete[] = {
+	{PMT_CAP_PETE_MAN_TRIG,		"manual_trigger"},
+	{PMT_CAP_PETE_ENCRYPTION,	"encryption"},
+	{PMT_CAP_PETE_PERSISTENCY,	"persistency"},
+	{PMT_CAP_PETE_REQ_TOKENS,	"required_tokens"},
+	{PMT_CAP_PETE_PROD_ENABLED,	"production_enabled"},
+	{PMT_CAP_PETE_DEBUG_ENABLED,	"debug_enabled"},
+	{}
+};
+
+struct pmt_cap *pmt_caps_pete[] = {
+	pmt_cap_common,
+	pmt_cap_pete,
+	NULL
+};
+
+struct pmt_cap pmt_cap_tpmi[] = {
+	{PMT_CAP_TPMI_MAILBOX,		"mailbox"},
+	{PMT_CAP_TPMI_LOCK,		"bios_lock"},
+	{}
+};
+
+struct pmt_cap *pmt_caps_tpmi[] = {
+	pmt_cap_common,
+	pmt_cap_tpmi,
+	NULL
+};
+
+struct pmt_cap pmt_cap_tracing[] = {
+	{PMT_CAP_TRACE_SRAR,		"srar_errors"},
+	{PMT_CAP_TRACE_CORRECTABLE,	"correctable_errors"},
+	{PMT_CAP_TRACE_MCTP,		"mctp"},
+	{PMT_CAP_TRACE_MRT,		"memory_resiliency"},
+	{}
+};
+
+struct pmt_cap *pmt_caps_tracing[] = {
+	pmt_cap_common,
+	pmt_cap_tracing,
+	NULL
+};
+
+struct pmt_cap pmt_cap_rmid_energy[] = {
+	{PMT_CAP_RMID_ENERGY,		"energy"},
+	{PMT_CAP_RMID_ACTIVITY,		"activity"},
+	{PMT_CAP_RMID_ENERGY_QUAL,	"energy_quality"},
+	{}
+};
+
+struct pmt_cap *pmt_caps_rmid_energy[] = {
+	pmt_cap_common,
+	pmt_cap_rmid_energy,
+	NULL
+};
diff --git a/include/linux/intel_pmt_features.h b/include/linux/intel_pmt_features.h
new file mode 100644
index 000000000000..53573a4a49b7
--- /dev/null
+++ b/include/linux/intel_pmt_features.h
@@ -0,0 +1,157 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _FEATURES_H
+#define _FEATURES_H
+
+#include <linux/bits.h>
+#include <linux/types.h>
+
+/* Common masks */
+#define PMT_CAP_TELEM			BIT(0)
+#define PMT_CAP_WATCHER			BIT(1)
+#define PMT_CAP_CRASHLOG		BIT(2)
+#define PMT_CAP_STREAMING		BIT(3)
+#define PMT_CAP_THRESHOLD		BIT(4)
+#define PMT_CAP_WINDOW			BIT(5)
+#define PMT_CAP_CONFIG			BIT(6)
+#define PMT_CAP_TRACING			BIT(7)
+#define PMT_CAP_INBAND			BIT(8)
+#define PMT_CAP_OOB			BIT(9)
+#define PMT_CAP_SECURED_CHAN		BIT(10)
+
+#define PMT_CAP_PMT_SP			BIT(11)
+#define PMT_CAP_PMT_SP_POLICY		GENMASK(17, 12)
+
+/* Per Core Performance Telemetry (PCPT) specific masks */
+#define PMT_CAP_PCPT_CORE_PERF		BIT(18)
+#define PMT_CAP_PCPT_CORE_C0_RES	BIT(19)
+#define PMT_CAP_PCPT_CORE_ACTIVITY	BIT(20)
+#define PMT_CAP_PCPT_CACHE_PERF		BIT(21)
+#define PMT_CAP_PCPT_QUALITY_TELEM	BIT(22)
+
+/* Per Core Environmental Telemetry (PCET) specific masks */
+#define PMT_CAP_PCET_WORKPOINT_HIST	BIT(18)
+#define PMT_CAP_PCET_CORE_CURR_TEMP	BIT(19)
+#define PMT_CAP_PCET_CORE_INST_RES	BIT(20)
+#define PMT_CAP_PCET_QUALITY_TELEM	BIT(21)	/* Same as PMT_CAP_PCPT */
+#define PMT_CAP_PCET_CORE_CDYN_LVL	BIT(22)
+#define PMT_CAP_PCET_CORE_STRESS_LVL	BIT(23)
+#define PMT_CAP_PCET_CORE_DAS		BIT(24)
+#define PMT_CAP_PCET_FIVR_HEALTH	BIT(25)
+#define PMT_CAP_PCET_ENERGY		BIT(26)
+#define PMT_CAP_PCET_PEM_STATUS		BIT(27)
+#define PMT_CAP_PCET_CORE_C_STATE	BIT(28)
+
+/* Per RMID Performance Telemetry specific masks */
+#define PMT_CAP_RMID_CORES_PERF		BIT(18)
+#define PMT_CAP_RMID_CACHE_PERF		BIT(19)
+#define PMT_CAP_RMID_PERF_QUAL		BIT(20)
+
+/* Accelerator Telemetry specific masks */
+#define PMT_CAP_ACCEL_CPM_TELEM		BIT(18)
+#define PMT_CAP_ACCEL_TIP_TELEM		BIT(19)
+
+/* Uncore Telemetry specific masks */
+#define PMT_CAP_UNCORE_IO_CA_TELEM	BIT(18)
+#define PMT_CAP_UNCORE_RMID_TELEM	BIT(19)
+#define PMT_CAP_UNCORE_D2D_ULA_TELEM	BIT(20)
+#define PMT_CAP_UNCORE_PKGC_TELEM	BIT(21)
+
+/* Crash Log specific masks */
+#define PMT_CAP_CRASHLOG_MAN_TRIG	BIT(11)
+#define PMT_CAP_CRASHLOG_CORE		BIT(12)
+#define PMT_CAP_CRASHLOG_UNCORE		BIT(13)
+#define PMT_CAP_CRASHLOG_TOR		BIT(14)
+#define PMT_CAP_CRASHLOG_S3M		BIT(15)
+#define PMT_CAP_CRASHLOG_PERSISTENCY	BIT(16)
+#define PMT_CAP_CRASHLOG_CLIP_GPIO	BIT(17)
+#define PMT_CAP_CRASHLOG_PRE_RESET	BIT(18)
+#define PMT_CAP_CRASHLOG_POST_RESET	BIT(19)
+
+/* PeTe Log specific masks */
+#define PMT_CAP_PETE_MAN_TRIG		BIT(11)
+#define PMT_CAP_PETE_ENCRYPTION		BIT(12)
+#define PMT_CAP_PETE_PERSISTENCY	BIT(13)
+#define PMT_CAP_PETE_REQ_TOKENS		BIT(14)
+#define PMT_CAP_PETE_PROD_ENABLED	BIT(15)
+#define PMT_CAP_PETE_DEBUG_ENABLED	BIT(16)
+
+/* TPMI control specific masks */
+#define PMT_CAP_TPMI_MAILBOX		BIT(11)
+#define PMT_CAP_TPMI_LOCK		BIT(12)
+
+/* Tracing specific masks */
+#define PMT_CAP_TRACE_SRAR		BIT(11)
+#define PMT_CAP_TRACE_CORRECTABLE	BIT(12)
+#define PMT_CAP_TRACE_MCTP		BIT(13)
+#define PMT_CAP_TRACE_MRT		BIT(14)
+
+/* Per RMID Energy Telemetry specific masks */
+#define PMT_CAP_RMID_ENERGY		BIT(18)
+#define PMT_CAP_RMID_ACTIVITY		BIT(19)
+#define PMT_CAP_RMID_ENERGY_QUAL	BIT(20)
+
+enum pmt_feature_id {
+	FEATURE_INVALID			= 0x0,
+	FEATURE_PER_CORE_PERF_TELEM	= 0x1,
+	FEATURE_PER_CORE_ENV_TELEM	= 0x2,
+	FEATURE_PER_RMID_PERF_TELEM	= 0x3,
+	FEATURE_ACCEL_TELEM		= 0x4,
+	FEATURE_UNCORE_TELEM		= 0x5,
+	FEATURE_CRASH_LOG		= 0x6,
+	FEATURE_PETE_LOG		= 0x7,
+	FEATURE_TPMI_CTRL		= 0x8,
+	FEATURE_RESERVED		= 0x9,
+	FEATURE_TRACING			= 0xA,
+	FEATURE_PER_RMID_ENERGY_TELEM	= 0xB,
+	FEATURE_MAX			= 0xB,
+};
+
+enum feature_layout {
+	LAYOUT_RMID,
+	LAYOUT_WATCHER,
+	LAYOUT_COMMAND,
+	LAYOUT_CAPS_ONLY,
+};
+
+struct pmt_cap {
+	u32		mask;
+	const char	*name;
+};
+
+extern const char * const pmt_feature_names[];
+extern enum feature_layout feature_layout[];
+extern struct pmt_cap pmt_cap_common[];
+extern struct pmt_cap pmt_cap_pcpt[];
+extern struct pmt_cap *pmt_caps_pcpt[];
+extern struct pmt_cap pmt_cap_pcet[];
+extern struct pmt_cap *pmt_caps_pcet[];
+extern struct pmt_cap pmt_cap_rmid_perf[];
+extern struct pmt_cap *pmt_caps_rmid_perf[];
+extern struct pmt_cap pmt_cap_accel[];
+extern struct pmt_cap *pmt_caps_accel[];
+extern struct pmt_cap pmt_cap_uncore[];
+extern struct pmt_cap *pmt_caps_uncore[];
+extern struct pmt_cap pmt_cap_crashlog[];
+extern struct pmt_cap *pmt_caps_crashlog[];
+extern struct pmt_cap pmt_cap_pete[];
+extern struct pmt_cap *pmt_caps_pete[];
+extern struct pmt_cap pmt_cap_tpmi[];
+extern struct pmt_cap *pmt_caps_tpmi[];
+extern struct pmt_cap pmt_cap_s3m[];
+extern struct pmt_cap *pmt_caps_s3m[];
+extern struct pmt_cap pmt_cap_tracing[];
+extern struct pmt_cap *pmt_caps_tracing[];
+extern struct pmt_cap pmt_cap_rmid_energy[];
+extern struct pmt_cap *pmt_caps_rmid_energy[];
+
+static inline bool pmt_feature_id_is_valid(enum pmt_feature_id id)
+{
+	if (id > FEATURE_MAX)
+		return false;
+
+	if (id == FEATURE_INVALID || id == FEATURE_RESERVED)
+		return false;
+
+	return true;
+}
+#endif
-- 
2.43.0


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

* [PATCH V3 09/15] docs: Add ABI documentation for intel_pmt feature directories
  2025-07-03  2:28 [PATCH V3 00/15] Intel VSEC/PMT: Introduce Discovery Driver David E. Box
                   ` (7 preceding siblings ...)
  2025-07-03  2:28 ` [PATCH V3 08/15] platform/x86/intel/pmt: Add PMT Discovery driver David E. Box
@ 2025-07-03  2:28 ` David E. Box
  2025-07-03  2:28 ` [PATCH V3 10/15] platform/x86/intel/tpmi: Relocate platform info to intel_vsec.h David E. Box
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: David E. Box @ 2025-07-03  2:28 UTC (permalink / raw)
  To: linux-kernel, platform-driver-x86, david.e.box,
	srinivas.pandruvada, andriy.shevchenko, ilpo.jarvinen, tony.luck,
	xi.pardee
  Cc: hdegoede

Add a new sysfs ABI documentation file describing the layout and content of
the features-<PCI BDF>/ directory used by Intel PMT (Platform Monitoring
Technology). This directory exposes telemetry and control feature details
for a given PMT PCI device.

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

Changes in v3:
  - No changes

Changes in v2:
  - Spell out RMID and add description of the feature.
  - Add a description of the watcher API
  - Update example to use snake case for pmt_sp_policy

 .../testing/sysfs-class-intel_pmt-features    | 134 ++++++++++++++++++
 MAINTAINERS                                   |   1 +
 2 files changed, 135 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-intel_pmt-features

diff --git a/Documentation/ABI/testing/sysfs-class-intel_pmt-features b/Documentation/ABI/testing/sysfs-class-intel_pmt-features
new file mode 100644
index 000000000000..cddb30e5bdf6
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-intel_pmt-features
@@ -0,0 +1,134 @@
+What:          /sys/class/intel_pmt/features-<PCI BDF>/
+Date:          2025-04-24
+KernelVersion: 6.16
+Contact:       david.e.box@linux.intel.com
+Description:
+               The `features-<PCI BDF>/` directory represents the "features"
+               capability exposed by Intel PMT (Platform Monitoring Technology)
+               for the given PCI device.
+
+               Each directory corresponds to a PMT feature and contains
+               attributes describing the available telemetry, monitoring, or
+               control functionalities.
+
+Directory Structure:
+
+  /sys/class/intel_pmt/features-<PCI BDF>/
+  ├── accelerator_telemetry/		# Per-accelerator telemetry data
+  ├── crash_log/			# Contains system crash telemetry logs
+  ├── per_core_environment_telemetry/	# Environmental telemetry per core
+  ├── per_core_performance_telemetry/	# Performance telemetry per core
+  ├── per_rmid_energy_telemetry/	# Energy telemetry for RMIDs
+  ├── per_rmid_perf_telemetry/		# Performance telemetry for RMIDs
+  ├── tpmi_control/			# TPMI-related controls and telemetry
+  ├── tracing/				# PMT tracing features
+  └── uncore_telemetry/			# Uncore telemetry data
+
+Common Files (Present in all feature directories):
+
+  caps
+    - Read-only
+    - Lists available capabilities for this feature.
+
+  guids
+    - Read-only
+    - Lists GUIDs associated with this feature.
+
+Additional Attributes (Conditional Presence):
+
+  max_command_size
+    - Read-only
+    - Present if the feature supports out-of-band MCTP access.
+    - Maximum supported MCTP command size for out-of-band PMT access (bytes).
+
+  max_stream_size
+    - Read-only
+    - Present if the feature supports out-of-band MCTP access.
+    - Maximum supported MCTP stream size (bytes).
+
+  min_watcher_period_ms
+    - Read-only
+    - Present if the feature supports the watcher API.
+      The watcher API provides a writable control interface that allows user
+      configuration of monitoring behavior, such as setting the sampling or
+      reporting interval.
+    - Minimum supported time period for the watcher interface (milliseconds).
+
+  num_rmids
+    - Read-only
+    - Present if the feature supports RMID (Resource Monitoring ID) telemetry.
+      RMIDs are identifiers used by hardware to track and report resource usage,
+      such as memory bandwidth or energy consumption, on a per-logical-entity
+      basis (e.g., per core, thread, or process group).
+    - Maximum number of RMIDs tracked simultaneously.
+
+Example:
+For a device with PCI BDF `0000:00:03.1`, the directory tree could look like:
+
+  /sys/class/intel_pmt/features-0000:00:03.1/
+  ├── accelerator_telemetry/
+  │   ├── caps
+  │   ├── guids
+  │   ├── max_command_size
+  │   ├── max_stream_size
+  │   ├── min_watcher_period_ms
+  ├── crash_log/
+  │   ├── caps
+  │   ├── guids
+  │   ├── max_command_size
+  │   ├── max_stream_size
+  ├── per_core_environment_telemetry/
+  │   ├── caps
+  │   ├── guids
+  │   ├── max_command_size
+  │   ├── max_stream_size
+  │   ├── min_watcher_period_ms
+  ├── per_rmid_energy_telemetry/
+  │   ├── caps
+  │   ├── guids
+  │   ├── max_command_size
+  │   ├── max_stream_size
+  │   ├── min_watcher_period_ms
+  │   ├── num_rmids
+  ├── tpmi_control/
+  │   ├── caps
+  │   ├── guids
+  ├── tracing/
+  │   ├── caps
+  │   ├── guids
+  ├── uncore_telemetry/
+  │   ├── caps
+  │   ├── guids
+  │   ├── max_command_size
+  │   ├── max_stream_size
+  │   ├── min_watcher_period_ms
+
+Notes:
+  - Some attributes are only present if the corresponding feature supports
+    the capability (e.g., `max_command_size` for MCTP-capable features).
+  - Features supporting RMIDs include `num_rmids`.
+  - Features supporting the watcher API include `min_watcher_period_ms`.
+  - The `caps` file provides additional information about the functionality
+    of the feature.
+
+Example 'caps' content for the 'tracing' feature:
+
+  /sys/class/intel_pmt/features-0000:00:03.1/
+  ├── tracing/
+  │   ├── caps
+
+	telemetry                                Available: No
+	watcher                                  Available: Yes
+	crashlog                                 Available: No
+	streaming                                Available: No
+	threashold                               Available: No
+	window                                   Available: No
+	config                                   Available: Yes
+	tracing                                  Available: No
+	inband                                   Available: Yes
+	oob                                      Available: Yes
+	secure_chan                              Available: No
+	pmt_sp                                   Available: Yes
+	pmt_sp_policy                            Available: Yes
+	mailbox                                  Available: Yes
+	bios_lock                                Available: Yes
diff --git a/MAINTAINERS b/MAINTAINERS
index b0a67f058393..dcf081547ce7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12389,6 +12389,7 @@ INTEL PMT DRIVERS
 M:	David E. Box <david.e.box@linux.intel.com>
 S:	Supported
 F:	Documentation/ABI/testing/sysfs-class-intel_pmt
+F:	Documentation/ABI/testing/sysfs-class-intel_pmt-features
 F:	drivers/platform/x86/intel/pmt/
 
 INTEL PRO/WIRELESS 2100, 2200BG, 2915ABG NETWORK CONNECTION SUPPORT
-- 
2.43.0


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

* [PATCH V3 10/15] platform/x86/intel/tpmi: Relocate platform info to intel_vsec.h
  2025-07-03  2:28 [PATCH V3 00/15] Intel VSEC/PMT: Introduce Discovery Driver David E. Box
                   ` (8 preceding siblings ...)
  2025-07-03  2:28 ` [PATCH V3 09/15] docs: Add ABI documentation for intel_pmt feature directories David E. Box
@ 2025-07-03  2:28 ` David E. Box
  2025-07-03  2:28 ` [PATCH V3 11/15] platform/x86/intel/vsec: Set OOBMSM to CPU mapping David E. Box
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: David E. Box @ 2025-07-03  2:28 UTC (permalink / raw)
  To: linux-kernel, platform-driver-x86, david.e.box,
	srinivas.pandruvada, andriy.shevchenko, ilpo.jarvinen, tony.luck,
	xi.pardee
  Cc: hdegoede

The TPMI platform information provides a mapping of OOBMSM PCI devices to
logical CPUs. Since this mapping is consistent across all OOBMSM features
(e.g., TPMI, PMT, SDSi), it can be leveraged by multiple drivers. To
facilitate reuse, relocate the struct intel_tpmi_plat_info to intel_vsec.h,
renaming it to struct oobmsm_plat_info, making it accessible to other
features. While modifying headers, place them in alphabetical order.

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

Changes in v3:
  - No changes

Changes in v2:
  - Add change for uncore-frequency-tmpi 6.16-rc1
  - In intel_tpmi.h add newline after headers
  
 drivers/platform/x86/intel/plr_tpmi.c         |  3 ++-
 .../intel/speed_select_if/isst_tpmi_core.c    |  9 ++++---
 .../uncore-frequency/uncore-frequency-tpmi.c  |  7 ++---
 drivers/platform/x86/intel/vsec_tpmi.c        |  4 +--
 drivers/powercap/intel_rapl_tpmi.c            |  9 ++++---
 include/linux/intel_tpmi.h                    | 27 +++----------------
 include/linux/intel_vsec.h                    | 22 +++++++++++++++
 7 files changed, 43 insertions(+), 38 deletions(-)

diff --git a/drivers/platform/x86/intel/plr_tpmi.c b/drivers/platform/x86/intel/plr_tpmi.c
index 2b55347a5a93..58132da47745 100644
--- a/drivers/platform/x86/intel/plr_tpmi.c
+++ b/drivers/platform/x86/intel/plr_tpmi.c
@@ -14,6 +14,7 @@
 #include <linux/err.h>
 #include <linux/gfp_types.h>
 #include <linux/intel_tpmi.h>
+#include <linux/intel_vsec.h>
 #include <linux/io.h>
 #include <linux/iopoll.h>
 #include <linux/kstrtox.h>
@@ -256,7 +257,7 @@ DEFINE_SHOW_STORE_ATTRIBUTE(plr_status);
 
 static int intel_plr_probe(struct auxiliary_device *auxdev, const struct auxiliary_device_id *id)
 {
-	struct intel_tpmi_plat_info *plat_info;
+	struct oobmsm_plat_info *plat_info;
 	struct dentry *dentry;
 	int i, num_resources;
 	struct resource *res;
diff --git a/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c b/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c
index 18c035710eb9..34bff2f65a83 100644
--- a/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c
+++ b/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c
@@ -22,6 +22,7 @@
 #include <linux/auxiliary_bus.h>
 #include <linux/delay.h>
 #include <linux/intel_tpmi.h>
+#include <linux/intel_vsec.h>
 #include <linux/fs.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
@@ -1546,7 +1547,7 @@ int tpmi_sst_dev_add(struct auxiliary_device *auxdev)
 {
 	struct tpmi_per_power_domain_info *pd_info;
 	bool read_blocked = 0, write_blocked = 0;
-	struct intel_tpmi_plat_info *plat_info;
+	struct oobmsm_plat_info *plat_info;
 	struct device *dev = &auxdev->dev;
 	struct tpmi_sst_struct *tpmi_sst;
 	u8 i, num_resources, io_die_cnt;
@@ -1698,7 +1699,7 @@ EXPORT_SYMBOL_NS_GPL(tpmi_sst_dev_add, "INTEL_TPMI_SST");
 void tpmi_sst_dev_remove(struct auxiliary_device *auxdev)
 {
 	struct tpmi_sst_struct *tpmi_sst = auxiliary_get_drvdata(auxdev);
-	struct intel_tpmi_plat_info *plat_info;
+	struct oobmsm_plat_info *plat_info;
 
 	plat_info = tpmi_get_platform_data(auxdev);
 	if (!plat_info)
@@ -1720,7 +1721,7 @@ void tpmi_sst_dev_suspend(struct auxiliary_device *auxdev)
 {
 	struct tpmi_sst_struct *tpmi_sst = auxiliary_get_drvdata(auxdev);
 	struct tpmi_per_power_domain_info *power_domain_info;
-	struct intel_tpmi_plat_info *plat_info;
+	struct oobmsm_plat_info *plat_info;
 	void __iomem *cp_base;
 
 	plat_info = tpmi_get_platform_data(auxdev);
@@ -1748,7 +1749,7 @@ void tpmi_sst_dev_resume(struct auxiliary_device *auxdev)
 {
 	struct tpmi_sst_struct *tpmi_sst = auxiliary_get_drvdata(auxdev);
 	struct tpmi_per_power_domain_info *power_domain_info;
-	struct intel_tpmi_plat_info *plat_info;
+	struct oobmsm_plat_info *plat_info;
 	void __iomem *cp_base;
 
 	plat_info = tpmi_get_platform_data(auxdev);
diff --git a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c
index 44d9948ed224..6df55c8e16b7 100644
--- a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c
+++ b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c
@@ -22,9 +22,10 @@
 #include <linux/auxiliary_bus.h>
 #include <linux/bitfield.h>
 #include <linux/bits.h>
+#include <linux/intel_tpmi.h>
+#include <linux/intel_vsec.h>
 #include <linux/io.h>
 #include <linux/module.h>
-#include <linux/intel_tpmi.h>
 
 #include "../tpmi_power_domains.h"
 #include "uncore-frequency-common.h"
@@ -448,7 +449,7 @@ static void remove_cluster_entries(struct tpmi_uncore_struct *tpmi_uncore)
 }
 
 static void set_cdie_id(int domain_id, struct tpmi_uncore_cluster_info *cluster_info,
-		       struct intel_tpmi_plat_info *plat_info)
+			struct oobmsm_plat_info *plat_info)
 {
 
 	cluster_info->cdie_id = domain_id;
@@ -465,7 +466,7 @@ static void set_cdie_id(int domain_id, struct tpmi_uncore_cluster_info *cluster_
 static int uncore_probe(struct auxiliary_device *auxdev, const struct auxiliary_device_id *id)
 {
 	bool read_blocked = 0, write_blocked = 0;
-	struct intel_tpmi_plat_info *plat_info;
+	struct oobmsm_plat_info *plat_info;
 	struct tpmi_uncore_struct *tpmi_uncore;
 	bool uncore_sysfs_added = false;
 	int ret, i, pkg = 0;
diff --git a/drivers/platform/x86/intel/vsec_tpmi.c b/drivers/platform/x86/intel/vsec_tpmi.c
index 5c383a27bbe8..d95a0d994546 100644
--- a/drivers/platform/x86/intel/vsec_tpmi.c
+++ b/drivers/platform/x86/intel/vsec_tpmi.c
@@ -116,7 +116,7 @@ struct intel_tpmi_info {
 	struct intel_vsec_device *vsec_dev;
 	int feature_count;
 	u64 pfs_start;
-	struct intel_tpmi_plat_info plat_info;
+	struct oobmsm_plat_info plat_info;
 	void __iomem *tpmi_control_mem;
 	struct dentry *dbgfs_dir;
 };
@@ -187,7 +187,7 @@ struct tpmi_feature_state {
 /* Used during auxbus device creation */
 static DEFINE_IDA(intel_vsec_tpmi_ida);
 
-struct intel_tpmi_plat_info *tpmi_get_platform_data(struct auxiliary_device *auxdev)
+struct oobmsm_plat_info *tpmi_get_platform_data(struct auxiliary_device *auxdev)
 {
 	struct intel_vsec_device *vsec_dev = auxdev_to_ivdev(auxdev);
 
diff --git a/drivers/powercap/intel_rapl_tpmi.c b/drivers/powercap/intel_rapl_tpmi.c
index af2368f4db10..82201bf4685d 100644
--- a/drivers/powercap/intel_rapl_tpmi.c
+++ b/drivers/powercap/intel_rapl_tpmi.c
@@ -9,9 +9,10 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/auxiliary_bus.h>
-#include <linux/io.h>
-#include <linux/intel_tpmi.h>
 #include <linux/intel_rapl.h>
+#include <linux/intel_tpmi.h>
+#include <linux/intel_vsec.h>
+#include <linux/io.h>
 #include <linux/module.h>
 #include <linux/slab.h>
 
@@ -48,7 +49,7 @@ enum tpmi_rapl_register {
 
 struct tpmi_rapl_package {
 	struct rapl_if_priv priv;
-	struct intel_tpmi_plat_info *tpmi_info;
+	struct oobmsm_plat_info *tpmi_info;
 	struct rapl_package *rp;
 	void __iomem *base;
 	struct list_head node;
@@ -253,7 +254,7 @@ static int intel_rapl_tpmi_probe(struct auxiliary_device *auxdev,
 				 const struct auxiliary_device_id *id)
 {
 	struct tpmi_rapl_package *trp;
-	struct intel_tpmi_plat_info *info;
+	struct oobmsm_plat_info *info;
 	struct resource *res;
 	u32 offset;
 	int ret;
diff --git a/include/linux/intel_tpmi.h b/include/linux/intel_tpmi.h
index ff480b47ae64..94c06bf214fb 100644
--- a/include/linux/intel_tpmi.h
+++ b/include/linux/intel_tpmi.h
@@ -8,6 +8,8 @@
 
 #include <linux/bitfield.h>
 
+struct oobmsm_plat_info;
+
 #define TPMI_VERSION_INVALID	0xff
 #define TPMI_MINOR_VERSION(val)	FIELD_GET(GENMASK(4, 0), val)
 #define TPMI_MAJOR_VERSION(val)	FIELD_GET(GENMASK(7, 5), val)
@@ -26,30 +28,7 @@ enum intel_tpmi_id {
 	TPMI_INFO_ID = 0x81,	/* Special ID for PCI BDF and Package ID information */
 };
 
-/**
- * struct intel_tpmi_plat_info - Platform information for a TPMI device instance
- * @cdie_mask:       Mask of all compute dies in the partition
- * @package_id:      CPU Package id
- * @partition:       Package partition id when multiple VSEC PCI devices per package
- * @segment:         PCI segment ID
- * @bus_number:      PCI bus number
- * @device_number:   PCI device number
- * @function_number: PCI function number
- *
- * Structure to store platform data for a TPMI device instance. This
- * struct is used to return data via tpmi_get_platform_data().
- */
-struct intel_tpmi_plat_info {
-	u16 cdie_mask;
-	u8 package_id;
-	u8 partition;
-	u8 segment;
-	u8 bus_number;
-	u8 device_number;
-	u8 function_number;
-};
-
-struct intel_tpmi_plat_info *tpmi_get_platform_data(struct auxiliary_device *auxdev);
+struct oobmsm_plat_info *tpmi_get_platform_data(struct auxiliary_device *auxdev);
 struct resource *tpmi_get_resource_at_index(struct auxiliary_device *auxdev, int index);
 int tpmi_get_resource_count(struct auxiliary_device *auxdev);
 int tpmi_get_feature_status(struct auxiliary_device *auxdev, int feature_id, bool *read_blocked,
diff --git a/include/linux/intel_vsec.h b/include/linux/intel_vsec.h
index a07796d7d43b..cd78d0b2e623 100644
--- a/include/linux/intel_vsec.h
+++ b/include/linux/intel_vsec.h
@@ -144,6 +144,28 @@ struct intel_vsec_device {
 	unsigned long cap_id;
 };
 
+/**
+ * struct oobmsm_plat_info - Platform information for a device instance
+ * @cdie_mask:       Mask of all compute dies in the partition
+ * @package_id:      CPU Package id
+ * @partition:       Package partition id when multiple VSEC PCI devices per package
+ * @segment:         PCI segment ID
+ * @bus_number:      PCI bus number
+ * @device_number:   PCI device number
+ * @function_number: PCI function number
+ *
+ * Structure to store platform data for a OOBMSM device instance.
+ */
+struct oobmsm_plat_info {
+	u16 cdie_mask;
+	u8 package_id;
+	u8 partition;
+	u8 segment;
+	u8 bus_number;
+	u8 device_number;
+	u8 function_number;
+};
+
 int intel_vsec_add_aux(struct pci_dev *pdev, struct device *parent,
 		       struct intel_vsec_device *intel_vsec_dev,
 		       const char *name);
-- 
2.43.0


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

* [PATCH V3 11/15] platform/x86/intel/vsec: Set OOBMSM to CPU mapping
  2025-07-03  2:28 [PATCH V3 00/15] Intel VSEC/PMT: Introduce Discovery Driver David E. Box
                   ` (9 preceding siblings ...)
  2025-07-03  2:28 ` [PATCH V3 10/15] platform/x86/intel/tpmi: Relocate platform info to intel_vsec.h David E. Box
@ 2025-07-03  2:28 ` David E. Box
  2025-07-03  2:28 ` [PATCH V3 12/15] platform/x86/intel/tpmi: Get OOBMSM CPU mapping from TPMI David E. Box
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: David E. Box @ 2025-07-03  2:28 UTC (permalink / raw)
  To: linux-kernel, platform-driver-x86, david.e.box,
	srinivas.pandruvada, andriy.shevchenko, ilpo.jarvinen, tony.luck,
	xi.pardee
  Cc: hdegoede

Add functions, intel_vsec_set/get_mapping(), to set and retrieve the
OOBMSM-to-CPU mapping data in the private data of the parent Intel VSEC
driver. With this mapping information available, other Intel VSEC features
on the same OOBMSM device can easily access and use the mapping data,
allowing each of the OOBMSM features to map to the CPUs they provides data
for.

Signed-off-by: David E. Box <david.e.box@linux.intel.com>
---
Changes in v3:
  - Drop unused intel_vsec_suppliers_read() declaration from
    intel_vsec.h.

Changes in v2:
  - No changes

 drivers/platform/x86/intel/vsec.c | 31 +++++++++++++++++++++++++++++++
 include/linux/intel_vsec.h        | 12 ++++++++++++
 2 files changed, 43 insertions(+)

diff --git a/drivers/platform/x86/intel/vsec.c b/drivers/platform/x86/intel/vsec.c
index 4d76f1ac3c8c..711ff4edfe21 100644
--- a/drivers/platform/x86/intel/vsec.c
+++ b/drivers/platform/x86/intel/vsec.c
@@ -44,6 +44,7 @@ enum vsec_device_state {
 struct vsec_priv {
 	struct intel_vsec_platform_info *info;
 	struct device *suppliers[VSEC_FEATURE_COUNT];
+	struct oobmsm_plat_info plat_info;
 	enum vsec_device_state state[VSEC_FEATURE_COUNT];
 	unsigned long found_caps;
 };
@@ -665,6 +666,36 @@ static int intel_vsec_pci_probe(struct pci_dev *pdev, const struct pci_device_id
 	return 0;
 }
 
+int intel_vsec_set_mapping(struct oobmsm_plat_info *plat_info,
+			   struct intel_vsec_device *vsec_dev)
+{
+	struct vsec_priv *priv;
+
+	priv = pci_get_drvdata(vsec_dev->pcidev);
+	if (!priv)
+		return -EINVAL;
+
+	priv->plat_info = *plat_info;
+
+	return 0;
+}
+EXPORT_SYMBOL_NS_GPL(intel_vsec_set_mapping, "INTEL_VSEC");
+
+struct oobmsm_plat_info *intel_vsec_get_mapping(struct pci_dev *pdev)
+{
+	struct vsec_priv *priv;
+
+	if (!pci_match_id(intel_vsec_pci_ids, pdev))
+		return ERR_PTR(-EINVAL);
+
+	priv = pci_get_drvdata(pdev);
+	if (!priv)
+		return ERR_PTR(-EINVAL);
+
+	return &priv->plat_info;
+}
+EXPORT_SYMBOL_NS_GPL(intel_vsec_get_mapping, "INTEL_VSEC");
+
 /* DG1 info */
 static struct intel_vsec_header dg1_header = {
 	.length = 0x10,
diff --git a/include/linux/intel_vsec.h b/include/linux/intel_vsec.h
index cd78d0b2e623..4bd0c6e7857c 100644
--- a/include/linux/intel_vsec.h
+++ b/include/linux/intel_vsec.h
@@ -183,11 +183,23 @@ static inline struct intel_vsec_device *auxdev_to_ivdev(struct auxiliary_device
 #if IS_ENABLED(CONFIG_INTEL_VSEC)
 int intel_vsec_register(struct pci_dev *pdev,
 			 struct intel_vsec_platform_info *info);
+int intel_vsec_set_mapping(struct oobmsm_plat_info *plat_info,
+			   struct intel_vsec_device *vsec_dev);
+struct oobmsm_plat_info *intel_vsec_get_mapping(struct pci_dev *pdev);
 #else
 static inline int intel_vsec_register(struct pci_dev *pdev,
 				       struct intel_vsec_platform_info *info)
 {
 	return -ENODEV;
 }
+static inline int intel_vsec_set_mapping(struct oobmsm_plat_info *plat_info,
+					 struct intel_vsec_device *vsec_dev)
+{
+	return -ENODEV;
+}
+static inline struct oobmsm_plat_info *intel_vsec_get_mapping(struct pci_dev *pdev)
+{
+	return ERR_PTR(-ENODEV);
+}
 #endif
 #endif
-- 
2.43.0


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

* [PATCH V3 12/15] platform/x86/intel/tpmi: Get OOBMSM CPU mapping from TPMI
  2025-07-03  2:28 [PATCH V3 00/15] Intel VSEC/PMT: Introduce Discovery Driver David E. Box
                   ` (10 preceding siblings ...)
  2025-07-03  2:28 ` [PATCH V3 11/15] platform/x86/intel/vsec: Set OOBMSM to CPU mapping David E. Box
@ 2025-07-03  2:28 ` David E. Box
  2025-07-03  2:28 ` [PATCH V3 13/15] platform/x86/intel/pmt/discovery: Get telemetry attributes David E. Box
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: David E. Box @ 2025-07-03  2:28 UTC (permalink / raw)
  To: linux-kernel, platform-driver-x86, david.e.box,
	srinivas.pandruvada, andriy.shevchenko, ilpo.jarvinen, tony.luck,
	xi.pardee
  Cc: hdegoede

Copy TPMI’s OOBMSM platform info into a common area within VSEC private
data via intel_vsec_set_mapping(). This enables other Intel VSEC features
to access the CPU mapping without additional queries.

Additionally, designate the TPMI driver as a supplier for the Telemetry
driver, ensuring it can obtain the necessary platform information for
future feature extensions.

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

Changes in v3:
  - No changes

Changes in v2:
  - Add missing comma in mtl_info

 drivers/platform/x86/intel/vsec.c      | 2 +-
 drivers/platform/x86/intel/vsec_tpmi.c | 4 ++++
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/platform/x86/intel/vsec.c b/drivers/platform/x86/intel/vsec.c
index 711ff4edfe21..f66f0ce8559b 100644
--- a/drivers/platform/x86/intel/vsec.c
+++ b/drivers/platform/x86/intel/vsec.c
@@ -725,7 +725,7 @@ static const struct intel_vsec_platform_info mtl_info = {
 static const struct vsec_feature_dependency oobmsm_deps[] = {
 	{
 		.feature = VSEC_CAP_TELEMETRY,
-		.supplier_bitmap = VSEC_CAP_DISCOVERY,
+		.supplier_bitmap = VSEC_CAP_DISCOVERY | VSEC_CAP_TPMI,
 	},
 };
 
diff --git a/drivers/platform/x86/intel/vsec_tpmi.c b/drivers/platform/x86/intel/vsec_tpmi.c
index d95a0d994546..7748b5557a18 100644
--- a/drivers/platform/x86/intel/vsec_tpmi.c
+++ b/drivers/platform/x86/intel/vsec_tpmi.c
@@ -799,6 +799,10 @@ static int intel_vsec_tpmi_init(struct auxiliary_device *auxdev)
 			ret = tpmi_process_info(tpmi_info, pfs);
 			if (ret)
 				return ret;
+
+			ret = intel_vsec_set_mapping(&tpmi_info->plat_info, vsec_dev);
+			if (ret)
+				return ret;
 		}
 
 		if (pfs->pfs_header.tpmi_id == TPMI_CONTROL_ID)
-- 
2.43.0


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

* [PATCH V3 13/15] platform/x86/intel/pmt/discovery: Get telemetry attributes
  2025-07-03  2:28 [PATCH V3 00/15] Intel VSEC/PMT: Introduce Discovery Driver David E. Box
                   ` (11 preceding siblings ...)
  2025-07-03  2:28 ` [PATCH V3 12/15] platform/x86/intel/tpmi: Get OOBMSM CPU mapping from TPMI David E. Box
@ 2025-07-03  2:28 ` David E. Box
  2025-07-03  2:28 ` [PATCH V3 14/15] platform/x86/intel/pmt/telemetry: Add API to retrieve telemetry regions by feature David E. Box
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: David E. Box @ 2025-07-03  2:28 UTC (permalink / raw)
  To: linux-kernel, platform-driver-x86, david.e.box,
	srinivas.pandruvada, andriy.shevchenko, ilpo.jarvinen, tony.luck,
	xi.pardee
  Cc: hdegoede

Add intel_pmt_get_features() in PMT Discovery to enable the PMT Telemetry
driver to obtain attributes of the aggregated telemetry spaces it
enumerates. The function gathers feature flags and associated data (like
the number of RMIDs) from each PMT entry, laying the groundwork for a
future kernel interface that will allow direct access to telemetry regions
based on their capabilities.

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

Changes in v3:
  - No changes

Changes in v2:
  - No changes

 drivers/platform/x86/intel/pmt/Kconfig     |  1 +
 drivers/platform/x86/intel/pmt/class.h     |  7 +++++
 drivers/platform/x86/intel/pmt/discovery.c | 33 ++++++++++++++++++++++
 drivers/platform/x86/intel/pmt/telemetry.c |  5 ++++
 include/linux/intel_vsec.h                 | 16 +++++++++++
 5 files changed, 62 insertions(+)

diff --git a/drivers/platform/x86/intel/pmt/Kconfig b/drivers/platform/x86/intel/pmt/Kconfig
index 0ad91b5112e9..83ae17eab462 100644
--- a/drivers/platform/x86/intel/pmt/Kconfig
+++ b/drivers/platform/x86/intel/pmt/Kconfig
@@ -18,6 +18,7 @@ config INTEL_PMT_CLASS
 config INTEL_PMT_TELEMETRY
 	tristate "Intel Platform Monitoring Technology (PMT) Telemetry driver"
 	depends on INTEL_VSEC
+	select INTEL_PMT_DISCOVERY
 	select INTEL_PMT_CLASS
 	help
 	  The Intel Platform Monitory Technology (PMT) Telemetry driver provides
diff --git a/drivers/platform/x86/intel/pmt/class.h b/drivers/platform/x86/intel/pmt/class.h
index 39c32357ee2c..fdf7e79d8c0d 100644
--- a/drivers/platform/x86/intel/pmt/class.h
+++ b/drivers/platform/x86/intel/pmt/class.h
@@ -48,6 +48,7 @@ struct intel_pmt_entry {
 	struct pmt_callbacks	*cb;
 	unsigned long		base_addr;
 	size_t			size;
+	u64			feature_flags;
 	u32			guid;
 	u32			num_rmids; /* Number of Resource Monitoring IDs */
 	int			devid;
@@ -71,4 +72,10 @@ int intel_pmt_dev_create(struct intel_pmt_entry *entry,
 			 struct intel_vsec_device *dev, int idx);
 void intel_pmt_dev_destroy(struct intel_pmt_entry *entry,
 			   struct intel_pmt_namespace *ns);
+#if IS_ENABLED(CONFIG_INTEL_PMT_DISCOVERY)
+void intel_pmt_get_features(struct intel_pmt_entry *entry);
+#else
+static inline void intel_pmt_get_features(struct intel_pmt_entry *entry) {}
+#endif
+
 #endif
diff --git a/drivers/platform/x86/intel/pmt/discovery.c b/drivers/platform/x86/intel/pmt/discovery.c
index 4b4fa3137ad2..e72d43b675b4 100644
--- a/drivers/platform/x86/intel/pmt/discovery.c
+++ b/drivers/platform/x86/intel/pmt/discovery.c
@@ -583,6 +583,39 @@ static int pmt_features_probe(struct auxiliary_device *auxdev, const struct auxi
 	return ret;
 }
 
+static void pmt_get_features(struct intel_pmt_entry *entry, struct feature *f)
+{
+	int num_guids = f->table.header.num_guids;
+	int i;
+
+	for (i = 0; i < num_guids; i++) {
+		if (f->table.guids[i] != entry->guid)
+			continue;
+
+		entry->feature_flags |= BIT(f->id);
+
+		if (feature_layout[f->id] == LAYOUT_RMID)
+			entry->num_rmids = f->table.rmid.num_rmids;
+		else
+			entry->num_rmids = 0; /* entry is kzalloc but set anyway */
+	}
+}
+
+void intel_pmt_get_features(struct intel_pmt_entry *entry)
+{
+	struct feature *feature;
+
+	mutex_lock(&feature_list_lock);
+	list_for_each_entry(feature, &pmt_feature_list, list) {
+		if (feature->priv->parent != &entry->ep->pcidev->dev)
+			continue;
+
+		pmt_get_features(entry, feature);
+	}
+	mutex_unlock(&feature_list_lock);
+}
+EXPORT_SYMBOL_NS_GPL(intel_pmt_get_features, "INTEL_PMT");
+
 static const struct auxiliary_device_id pmt_features_id_table[] = {
 	{ .name = "intel_vsec.discovery" },
 	{}
diff --git a/drivers/platform/x86/intel/pmt/telemetry.c b/drivers/platform/x86/intel/pmt/telemetry.c
index ac3a9bdf5601..58d06749e417 100644
--- a/drivers/platform/x86/intel/pmt/telemetry.c
+++ b/drivers/platform/x86/intel/pmt/telemetry.c
@@ -9,11 +9,14 @@
  */
 
 #include <linux/auxiliary_bus.h>
+#include <linux/intel_pmt_features.h>
 #include <linux/intel_vsec.h>
 #include <linux/kernel.h>
+#include <linux/kref.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
+#include <linux/types.h>
 #include <linux/uaccess.h>
 #include <linux/overflow.h>
 
@@ -311,6 +314,8 @@ static int pmt_telem_probe(struct auxiliary_device *auxdev, const struct auxilia
 			continue;
 
 		priv->num_entries++;
+
+		intel_pmt_get_features(entry);
 	}
 
 	return 0;
diff --git a/include/linux/intel_vsec.h b/include/linux/intel_vsec.h
index 4bd0c6e7857c..f185e9c01c90 100644
--- a/include/linux/intel_vsec.h
+++ b/include/linux/intel_vsec.h
@@ -4,6 +4,7 @@
 
 #include <linux/auxiliary_bus.h>
 #include <linux/bits.h>
+#include <linux/intel_pmt_features.h>
 
 /*
  * VSEC_CAP_UNUSED is reserved. It exists to prevent zero initialized
@@ -166,6 +167,21 @@ struct oobmsm_plat_info {
 	u8 function_number;
 };
 
+struct telemetry_region {
+	struct oobmsm_plat_info	plat_info;
+	void __iomem		*addr;
+	size_t			size;
+	u32			guid;
+	u32			num_rmids;
+};
+
+struct pmt_feature_group {
+	enum pmt_feature_id	id;
+	int			count;
+	struct kref		kref;
+	struct telemetry_region	regions[];
+};
+
 int intel_vsec_add_aux(struct pci_dev *pdev, struct device *parent,
 		       struct intel_vsec_device *intel_vsec_dev,
 		       const char *name);
-- 
2.43.0


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

* [PATCH V3 14/15] platform/x86/intel/pmt/telemetry: Add API to retrieve telemetry regions by feature
  2025-07-03  2:28 [PATCH V3 00/15] Intel VSEC/PMT: Introduce Discovery Driver David E. Box
                   ` (12 preceding siblings ...)
  2025-07-03  2:28 ` [PATCH V3 13/15] platform/x86/intel/pmt/discovery: Get telemetry attributes David E. Box
@ 2025-07-03  2:28 ` David E. Box
  2025-07-03  2:28 ` [PATCH V3 15/15] platform/x86/intel/pmt: KUNIT test for PMT Enhanced Discovery API David E. Box
  2025-07-03  8:10 ` [PATCH V3 00/15] Intel VSEC/PMT: Introduce Discovery Driver Ilpo Järvinen
  15 siblings, 0 replies; 17+ messages in thread
From: David E. Box @ 2025-07-03  2:28 UTC (permalink / raw)
  To: linux-kernel, platform-driver-x86, david.e.box,
	srinivas.pandruvada, andriy.shevchenko, ilpo.jarvinen, tony.luck,
	xi.pardee
  Cc: hdegoede

Introduce a new API, intel_pmt_get_regions_by_feature(), that gathers
telemetry regions based on a provided capability flag. This API enables
retrieval of regions with various capabilities (for example, RMID-based
telemetry) and provides a unified interface for accessing them. Resource
management is handled via reference counting using
intel_pmt_put_feature_group().

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

Changes in v3:
  - No changes

Changes in v2:
  - In pmt_telem_get_endpoint_info() use __free() for feature_group
  - Add missing header for ERR_PTR()
  - Split static inline function into multiple lines

 drivers/platform/x86/intel/pmt/telemetry.c | 89 +++++++++++++++++++++-
 include/linux/intel_vsec.h                 | 18 +++++
 2 files changed, 106 insertions(+), 1 deletion(-)

diff --git a/drivers/platform/x86/intel/pmt/telemetry.c b/drivers/platform/x86/intel/pmt/telemetry.c
index 58d06749e417..a4dfca6cac19 100644
--- a/drivers/platform/x86/intel/pmt/telemetry.c
+++ b/drivers/platform/x86/intel/pmt/telemetry.c
@@ -9,16 +9,21 @@
  */
 
 #include <linux/auxiliary_bus.h>
+#include <linux/bitops.h>
+#include <linux/cleanup.h>
+#include <linux/err.h>
 #include <linux/intel_pmt_features.h>
 #include <linux/intel_vsec.h>
 #include <linux/kernel.h>
 #include <linux/kref.h>
 #include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/overflow.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/types.h>
 #include <linux/uaccess.h>
-#include <linux/overflow.h>
+#include <linux/xarray.h>
 
 #include "class.h"
 
@@ -209,6 +214,87 @@ int pmt_telem_get_endpoint_info(int devid, struct telem_endpoint_info *info)
 }
 EXPORT_SYMBOL_NS_GPL(pmt_telem_get_endpoint_info, "INTEL_PMT_TELEMETRY");
 
+static int pmt_copy_region(struct telemetry_region *region,
+			   struct intel_pmt_entry *entry)
+{
+
+	struct oobmsm_plat_info *plat_info;
+
+	plat_info = intel_vsec_get_mapping(entry->ep->pcidev);
+	if (IS_ERR(plat_info))
+		return PTR_ERR(plat_info);
+
+	region->plat_info = *plat_info;
+	region->guid = entry->guid;
+	region->addr = entry->ep->base;
+	region->size = entry->size;
+	region->num_rmids = entry->num_rmids;
+
+	return 0;
+}
+
+static void pmt_feature_group_release(struct kref *kref)
+{
+	struct pmt_feature_group *feature_group;
+
+	feature_group = container_of(kref, struct pmt_feature_group, kref);
+	kfree(feature_group);
+}
+
+struct pmt_feature_group *intel_pmt_get_regions_by_feature(enum pmt_feature_id id)
+{
+	struct pmt_feature_group *feature_group __free(kfree) = NULL;
+	struct telemetry_region *region;
+	struct intel_pmt_entry *entry;
+	unsigned long idx;
+	int count = 0;
+	size_t size;
+
+	if (!pmt_feature_id_is_valid(id))
+		return ERR_PTR(-EINVAL);
+
+	guard(mutex)(&ep_lock);
+	xa_for_each(&telem_array, idx, entry) {
+		if (entry->feature_flags & BIT(id))
+			count++;
+	}
+
+	if (!count)
+		return ERR_PTR(-ENOENT);
+
+	size = struct_size(feature_group, regions, count);
+	feature_group = kzalloc(size, GFP_KERNEL);
+	if (!feature_group)
+		return ERR_PTR(-ENOMEM);
+
+	feature_group->count = count;
+
+	region = feature_group->regions;
+	xa_for_each(&telem_array, idx, entry) {
+		int ret;
+
+		if (!(entry->feature_flags & BIT(id)))
+			continue;
+
+		ret = pmt_copy_region(region, entry);
+		if (ret)
+			return ERR_PTR(ret);
+
+		region++;
+	}
+
+	kref_init(&feature_group->kref);
+
+	return no_free_ptr(feature_group);
+}
+EXPORT_SYMBOL(intel_pmt_get_regions_by_feature);
+
+void intel_pmt_put_feature_group(struct pmt_feature_group *feature_group)
+{
+	kref_put(&feature_group->kref, pmt_feature_group_release);
+}
+EXPORT_SYMBOL(intel_pmt_put_feature_group);
+
 int pmt_telem_read(struct telem_endpoint *ep, u32 id, u64 *data, u32 count)
 {
 	u32 offset, size;
@@ -353,3 +439,4 @@ MODULE_AUTHOR("David E. Box <david.e.box@linux.intel.com>");
 MODULE_DESCRIPTION("Intel PMT Telemetry driver");
 MODULE_LICENSE("GPL v2");
 MODULE_IMPORT_NS("INTEL_PMT");
+MODULE_IMPORT_NS("INTEL_VSEC");
diff --git a/include/linux/intel_vsec.h b/include/linux/intel_vsec.h
index f185e9c01c90..53f6fe88e369 100644
--- a/include/linux/intel_vsec.h
+++ b/include/linux/intel_vsec.h
@@ -4,6 +4,7 @@
 
 #include <linux/auxiliary_bus.h>
 #include <linux/bits.h>
+#include <linux/err.h>
 #include <linux/intel_pmt_features.h>
 
 /*
@@ -218,4 +219,21 @@ static inline struct oobmsm_plat_info *intel_vsec_get_mapping(struct pci_dev *pd
 	return ERR_PTR(-ENODEV);
 }
 #endif
+
+#if IS_ENABLED(CONFIG_INTEL_PMT_TELEMETRY)
+struct pmt_feature_group *
+intel_pmt_get_regions_by_feature(enum pmt_feature_id id);
+
+void intel_pmt_put_feature_group(struct pmt_feature_group *feature_group);
+#else
+static inline struct pmt_feature_group *
+intel_pmt_get_regions_by_feature(enum pmt_feature_id id)
+{
+	return ERR_PTR(-ENODEV);
+}
+
+static inline void
+intel_pmt_put_feature_group(struct pmt_feature_group *feature_group) {}
+#endif
+
 #endif
-- 
2.43.0


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

* [PATCH V3 15/15] platform/x86/intel/pmt: KUNIT test for PMT Enhanced Discovery API
  2025-07-03  2:28 [PATCH V3 00/15] Intel VSEC/PMT: Introduce Discovery Driver David E. Box
                   ` (13 preceding siblings ...)
  2025-07-03  2:28 ` [PATCH V3 14/15] platform/x86/intel/pmt/telemetry: Add API to retrieve telemetry regions by feature David E. Box
@ 2025-07-03  2:28 ` David E. Box
  2025-07-03  8:10 ` [PATCH V3 00/15] Intel VSEC/PMT: Introduce Discovery Driver Ilpo Järvinen
  15 siblings, 0 replies; 17+ messages in thread
From: David E. Box @ 2025-07-03  2:28 UTC (permalink / raw)
  To: linux-kernel, platform-driver-x86, david.e.box,
	srinivas.pandruvada, andriy.shevchenko, ilpo.jarvinen, tony.luck,
	xi.pardee
  Cc: hdegoede

Adds a KUNIT test for the intel_pmt_get_regions_by_feature() API.

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

Changes in v3:
  - No changes

Changes in v2:
  - No changes

 drivers/platform/x86/intel/pmt/Kconfig        |  14 +++
 drivers/platform/x86/intel/pmt/Makefile       |   2 +
 .../platform/x86/intel/pmt/discovery-kunit.c  | 116 ++++++++++++++++++
 3 files changed, 132 insertions(+)
 create mode 100644 drivers/platform/x86/intel/pmt/discovery-kunit.c

diff --git a/drivers/platform/x86/intel/pmt/Kconfig b/drivers/platform/x86/intel/pmt/Kconfig
index 83ae17eab462..83e20afc5655 100644
--- a/drivers/platform/x86/intel/pmt/Kconfig
+++ b/drivers/platform/x86/intel/pmt/Kconfig
@@ -51,3 +51,17 @@ config INTEL_PMT_DISCOVERY
 
 	  To compile this driver as a module, choose M here: the module
 	  will be called pmt_discovery.
+
+config INTEL_PMT_KUNIT_TEST
+	tristate "KUnit tests for Intel PMT driver"
+	depends on INTEL_PMT_DISCOVERY
+	depends on KUNIT
+	help
+	  Enable this option to compile and run a suite of KUnit tests for the Intel
+	  Platform Monitoring Technology (PMT) driver. These tests are designed to
+	  validate the driver's functionality, error handling, and overall stability,
+	  helping developers catch regressions and ensure code quality during changes.
+
+	  This option is intended for development and testing environments. It is
+	  recommended to disable it in production builds. To compile this driver as a
+	  module, choose M here: the module will be called pmt-discovery-kunit.
diff --git a/drivers/platform/x86/intel/pmt/Makefile b/drivers/platform/x86/intel/pmt/Makefile
index 8aed7e1592e4..47f692c091c9 100644
--- a/drivers/platform/x86/intel/pmt/Makefile
+++ b/drivers/platform/x86/intel/pmt/Makefile
@@ -12,3 +12,5 @@ obj-$(CONFIG_INTEL_PMT_CRASHLOG)	+= pmt_crashlog.o
 pmt_crashlog-y				:= crashlog.o
 obj-$(CONFIG_INTEL_PMT_DISCOVERY)	+= pmt_discovery.o
 pmt_discovery-y				:= discovery.o features.o
+obj-$(CONFIG_INTEL_PMT_KUNIT_TEST)	+= pmt-discovery-kunit.o
+pmt-discovery-kunit-y			:= discovery-kunit.o
diff --git a/drivers/platform/x86/intel/pmt/discovery-kunit.c b/drivers/platform/x86/intel/pmt/discovery-kunit.c
new file mode 100644
index 000000000000..b4493fb96738
--- /dev/null
+++ b/drivers/platform/x86/intel/pmt/discovery-kunit.c
@@ -0,0 +1,116 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Intel Platform Monitory Technology Discovery KUNIT tests
+ *
+ * Copyright (c) 2025, Intel Corporation.
+ * All Rights Reserved.
+ */
+
+#include <kunit/test.h>
+#include <linux/err.h>
+#include <linux/intel_pmt_features.h>
+#include <linux/intel_vsec.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#define PMT_FEATURE_COUNT (FEATURE_MAX + 1)
+
+static void
+validate_pmt_regions(struct kunit *test, struct pmt_feature_group *feature_group, int feature_id)
+{
+	int i;
+
+	kunit_info(test, "Feature ID %d [%s] has %d regions.\n", feature_id,
+		   pmt_feature_names[feature_id], feature_group->count);
+
+	for (i = 0; i < feature_group->count; i++) {
+		struct telemetry_region *region = &feature_group->regions[i];
+
+		kunit_info(test, "  - Region %d: cdie_mask=%u, package_id=%u, partition=%u, segment=%u,",
+			   i, region->plat_info.cdie_mask, region->plat_info.package_id,
+			   region->plat_info.partition, region->plat_info.segment);
+		kunit_info(test, "\t\tbus=%u, device=%u, function=%u, guid=0x%x,",
+			   region->plat_info.bus_number, region->plat_info.device_number,
+			   region->plat_info.function_number, region->guid);
+		kunit_info(test, "\t\taddr=%p, size=%lu, num_rmids=%u", region->addr, region->size,
+			   region->num_rmids);
+
+
+		KUNIT_ASSERT_GE(test, region->plat_info.cdie_mask, 0);
+		KUNIT_ASSERT_GE(test, region->plat_info.package_id, 0);
+		KUNIT_ASSERT_GE(test, region->plat_info.partition, 0);
+		KUNIT_ASSERT_GE(test, region->plat_info.segment, 0);
+		KUNIT_ASSERT_GE(test, region->plat_info.bus_number, 0);
+		KUNIT_ASSERT_GE(test, region->plat_info.device_number, 0);
+		KUNIT_ASSERT_GE(test, region->plat_info.function_number, 0);
+
+		KUNIT_ASSERT_NE(test, region->guid, 0);
+
+		KUNIT_ASSERT_NOT_ERR_OR_NULL(test, (__force const void *)region->addr);
+	}
+}
+
+static void linebreak(struct kunit *test)
+{
+	kunit_info(test, "*****************************************************************************\n");
+}
+
+static void test_intel_pmt_get_regions_by_feature(struct kunit *test)
+{
+	struct pmt_feature_group *feature_group;
+	int num_available = 0;
+	int feature_id;
+
+	/* Iterate through all possible feature IDs */
+	for (feature_id = 1; feature_id < PMT_FEATURE_COUNT; feature_id++, linebreak(test)) {
+		const char *name;
+
+		if (!pmt_feature_id_is_valid(feature_id))
+			continue;
+
+		name = pmt_feature_names[feature_id];
+
+		feature_group = intel_pmt_get_regions_by_feature(feature_id);
+		if (IS_ERR(feature_group)) {
+			if (PTR_ERR(feature_group) == -ENOENT)
+				kunit_warn(test, "intel_pmt_get_regions_by_feature() reporting feature %d [%s] is not present.\n",
+					   feature_id, name);
+			else
+				kunit_warn(test, "intel_pmt_get_regions_by_feature() returned error %ld while attempt to lookup %d [%s].\n",
+					   PTR_ERR(feature_group), feature_id, name);
+
+			continue;
+		}
+
+		if (!feature_group) {
+			kunit_warn(test, "Feature ID %d: %s is not available.\n", feature_id, name);
+			continue;
+		}
+
+		num_available++;
+
+		validate_pmt_regions(test, feature_group, feature_id);
+
+		intel_pmt_put_feature_group(feature_group);
+	}
+
+	if (num_available == 0)
+		kunit_warn(test, "No PMT region groups were available for any feature ID (0-10).\n");
+}
+
+static struct kunit_case intel_pmt_discovery_test_cases[] = {
+	KUNIT_CASE(test_intel_pmt_get_regions_by_feature),
+	{}
+};
+
+static struct kunit_suite intel_pmt_discovery_test_suite = {
+	.name = "pmt_discovery_test",
+	.test_cases = intel_pmt_discovery_test_cases,
+};
+
+kunit_test_suite(intel_pmt_discovery_test_suite);
+
+MODULE_IMPORT_NS("INTEL_PMT_DISCOVERY");
+MODULE_AUTHOR("David E. Box <david.e.box@linux.intel.com>");
+MODULE_DESCRIPTION("Intel PMT Discovery KUNIT test driver");
+MODULE_LICENSE("GPL");
-- 
2.43.0


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

* Re: [PATCH V3 00/15] Intel VSEC/PMT: Introduce Discovery Driver
  2025-07-03  2:28 [PATCH V3 00/15] Intel VSEC/PMT: Introduce Discovery Driver David E. Box
                   ` (14 preceding siblings ...)
  2025-07-03  2:28 ` [PATCH V3 15/15] platform/x86/intel/pmt: KUNIT test for PMT Enhanced Discovery API David E. Box
@ 2025-07-03  8:10 ` Ilpo Järvinen
  15 siblings, 0 replies; 17+ messages in thread
From: Ilpo Järvinen @ 2025-07-03  8:10 UTC (permalink / raw)
  To: linux-kernel, platform-driver-x86, srinivas.pandruvada,
	andriy.shevchenko, tony.luck, xi.pardee, David E. Box
  Cc: Hans de Goede

On Wed, 02 Jul 2025 19:28:15 -0700, David E. Box wrote:

> This patch series introduces a new discovery driver for Intel Platform
> Monitoring Technology (PMT) and a set of supporting changes to improve
> telemetry integration across Intel VSEC features.
> 
> The primary goal of this series is to add the PMT Discovery driver, which
> enumerates and exposes telemetry attributes by parsing hardware-provided
> discovery tables from OOBMSM devices. In particular, the discovery driver
> gathers detailed capability information (such as telemetry region
> attributes) that will later enable direct access to telemetry regions via a
> new API (intel_pmt_get_regions_by_feature()). This API is crucial for
> retrieving data like per-RMID counters.
> 
> [...]


Thank you for your contribution, it has been applied to my local
review-ilpo-next branch. Note it will show up in the public
platform-drivers-x86/review-ilpo-next branch only once I've pushed my
local branch there, which might take a while.

The list of commits applied:
[01/15] MAINTAINERS: Add link to documentation of Intel PMT ABI
        commit: fb1311b3f171bbb3c07cc7764ec981605564c83a
[02/15] platform/x86/intel/vsec: Add private data for per-device data
        commit: dc957ab6aa05c118c3da0542428a4d6602aa2d2d
[03/15] platform/x86/intel/vsec: Create wrapper to walk PCI config space
        commit: b0631f8a5740c55b52d02174cc4c9c84cc7a16a1
[04/15] platform/x86/intel/vsec: Add device links to enforce dependencies
        commit: 8a67d4b49bbdebcd255abde9e652092c3de3b657
[05/15] platform/x86/intel/vsec: Skip absent features during initialization
        commit: 1f3855ea7d6b03f68c2eec7a0bcd537cedcc6680
[06/15] platform/x86/intel/vsec: Skip driverless features
        commit: e4436e98672c7993cdfd7743efd0fcaa8df7cc17
[07/15] platform/x86/intel/vsec: Add new Discovery feature
        commit: 10f32796e86c04f73b7f8580cc9483765ed19f49
[08/15] platform/x86/intel/pmt: Add PMT Discovery driver
        commit: d9a0788093565c300f7c8dd034dbfa6ac4da9aa6
[09/15] docs: Add ABI documentation for intel_pmt feature directories
        commit: 2e7ba52110ef15d29846b40eb28b400f1fb1834a
[10/15] platform/x86/intel/tpmi: Relocate platform info to intel_vsec.h
        commit: 934954df0f44de5e10afc1af84c06f78149f15fe
[11/15] platform/x86/intel/vsec: Set OOBMSM to CPU mapping
        commit: a885a2780937afac4f31f00d11663f50d05dfb35
[12/15] platform/x86/intel/tpmi: Get OOBMSM CPU mapping from TPMI
        commit: c9699057521834862616ce159a47bd33920f0d9f
[13/15] platform/x86/intel/pmt/discovery: Get telemetry attributes
        commit: 86fc85c75bcd9b0f28afadd60c9f890669b42ba4
[14/15] platform/x86/intel/pmt/telemetry: Add API to retrieve telemetry regions by feature
        commit: 42dabe5442887946b16e64c6ebe91d2671a96fbb
[15/15] platform/x86/intel/pmt: KUNIT test for PMT Enhanced Discovery API
        commit: b9707d46a95962bb4e28ae1929015e419ad6aff7

--
 i.


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

end of thread, other threads:[~2025-07-03  8:10 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-03  2:28 [PATCH V3 00/15] Intel VSEC/PMT: Introduce Discovery Driver David E. Box
2025-07-03  2:28 ` [PATCH V3 01/15] MAINTAINERS: Add link to documentation of Intel PMT ABI David E. Box
2025-07-03  2:28 ` [PATCH V3 02/15] platform/x86/intel/vsec: Add private data for per-device data David E. Box
2025-07-03  2:28 ` [PATCH V3 03/15] platform/x86/intel/vsec: Create wrapper to walk PCI config space David E. Box
2025-07-03  2:28 ` [PATCH V3 04/15] platform/x86/intel/vsec: Add device links to enforce dependencies David E. Box
2025-07-03  2:28 ` [PATCH V3 05/15] platform/x86/intel/vsec: Skip absent features during initialization David E. Box
2025-07-03  2:28 ` [PATCH V3 06/15] platform/x86/intel/vsec: Skip driverless features David E. Box
2025-07-03  2:28 ` [PATCH V3 07/15] platform/x86/intel/vsec: Add new Discovery feature David E. Box
2025-07-03  2:28 ` [PATCH V3 08/15] platform/x86/intel/pmt: Add PMT Discovery driver David E. Box
2025-07-03  2:28 ` [PATCH V3 09/15] docs: Add ABI documentation for intel_pmt feature directories David E. Box
2025-07-03  2:28 ` [PATCH V3 10/15] platform/x86/intel/tpmi: Relocate platform info to intel_vsec.h David E. Box
2025-07-03  2:28 ` [PATCH V3 11/15] platform/x86/intel/vsec: Set OOBMSM to CPU mapping David E. Box
2025-07-03  2:28 ` [PATCH V3 12/15] platform/x86/intel/tpmi: Get OOBMSM CPU mapping from TPMI David E. Box
2025-07-03  2:28 ` [PATCH V3 13/15] platform/x86/intel/pmt/discovery: Get telemetry attributes David E. Box
2025-07-03  2:28 ` [PATCH V3 14/15] platform/x86/intel/pmt/telemetry: Add API to retrieve telemetry regions by feature David E. Box
2025-07-03  2:28 ` [PATCH V3 15/15] platform/x86/intel/pmt: KUNIT test for PMT Enhanced Discovery API David E. Box
2025-07-03  8:10 ` [PATCH V3 00/15] Intel VSEC/PMT: Introduce Discovery Driver Ilpo Järvinen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).