platform/x86/intel/pmt/telemetry: Add API to retrieve telemetry regions by feature

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>
Link: https://lore.kernel.org/r/20250703022832.1302928-15-david.e.box@linux.intel.com
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
This commit is contained in:
David E. Box
2025-07-02 19:28:29 -07:00
committed by Ilpo Järvinen
parent 86fc85c75b
commit 42dabe5442
2 changed files with 106 additions and 1 deletions

View File

@@ -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 @@ unlock:
}
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");

View File

@@ -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