[PATCH v1 2/2] platform/x86/intel-uncore-freq: Expose instance ID in the sysfs

Maciej Wieczor-Retman posted 2 patches 6 days ago
[PATCH v1 2/2] platform/x86/intel-uncore-freq: Expose instance ID in the sysfs
Posted by Maciej Wieczor-Retman 6 days ago
From: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>

To allow userspace matching between the kernel driver and direct TPMI
register accesses, expose the data required to identify a TPMI uncore
frequency control register set.

Specifically expose the instance ID that's unique in the scope of one
TPMI device. The value was previously available through the domain_id
file exported through sysfs. However on newer systems with multiple
clusters attached to a single instance, domain_id is taking on a unique
value, that's not local to the single TPMI device anymore.

Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
---
 .../uncore-frequency/uncore-frequency-common.c  | 10 ++++++++++
 .../uncore-frequency/uncore-frequency-common.h  |  6 +++++-
 .../uncore-frequency/uncore-frequency-tpmi.c    | 17 ++++++++++++++++-
 3 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c
index 71c47aa77d3c..52a62cad35de 100644
--- a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c
+++ b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c
@@ -29,6 +29,13 @@ static ssize_t show_domain_id(struct kobject *kobj, struct kobj_attribute *attr,
 	return sysfs_emit(buf, "%u\n", data->domain_id);
 }
 
+static ssize_t show_instance_id(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+	struct uncore_data *data = container_of(attr, struct uncore_data, instance_id_kobj_attr);
+
+	return sprintf(buf, "%u\n", data->instance_id);
+}
+
 static ssize_t show_fabric_cluster_id(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
 {
 	struct uncore_data *data = container_of(attr, struct uncore_data, fabric_cluster_id_kobj_attr);
@@ -200,6 +207,9 @@ static int create_attr_group(struct uncore_data *data, char *name)
 	if (data->domain_id != UNCORE_DOMAIN_ID_INVALID) {
 		init_attribute_root_ro(domain_id);
 		data->uncore_attrs[index++] = &data->domain_id_kobj_attr.attr;
+		init_attribute_root_ro(instance_id);
+		data->uncore_attrs[index++] = &data->instance_id_kobj_attr.attr;
+
 		init_attribute_root_ro(fabric_cluster_id);
 		data->uncore_attrs[index++] = &data->fabric_cluster_id_kobj_attr.attr;
 		init_attribute_root_ro(package_id);
diff --git a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.h b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.h
index 915506de4ebf..5e00030fedc5 100644
--- a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.h
+++ b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.h
@@ -36,6 +36,7 @@
  * @domain_id:		Power domain id for this instance
  * @cluster_id:		cluster id in a domain
  * @seqname_id:		Unique id to append to directory name
+ * @instance_id:	Feature instances for a single PCI device
  * @name:		Sysfs entry name for this instance
  * @agent_type_mask:	Bit mask of all hardware agents for this domain
  * @uncore_attr_group:	Attribute group storage
@@ -56,6 +57,7 @@
  * @elc_floor_freq_khz_kobj_attr: Storage for kobject attribute elc_floor_freq_khz
  * @agent_types_kobj_attr: Storage for kobject attribute agent_type
  * @die_id_kobj_attr:	Attribute storage for die_id information
+ * @instance_id_kobj_attr: Attribute storage for feat_instance value
  * @uncore_attrs:	Attribute storage for group creation
  *
  * This structure is used to encapsulate all data related to uncore sysfs
@@ -72,6 +74,7 @@ struct uncore_data {
 	int domain_id;
 	int cluster_id;
 	int seqname_id;
+	int instance_id;
 	char name[32];
 	u16  agent_type_mask;
 
@@ -90,7 +93,8 @@ struct uncore_data {
 	struct kobj_attribute elc_floor_freq_khz_kobj_attr;
 	struct kobj_attribute agent_types_kobj_attr;
 	struct kobj_attribute die_id_kobj_attr;
-	struct attribute *uncore_attrs[15];
+	struct kobj_attribute instance_id_kobj_attr;
+	struct attribute *uncore_attrs[16];
 };
 
 #define UNCORE_DOMAIN_ID_INVALID	-1
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 1237d9570886..e74e7d2e26b6 100644
--- a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c
+++ b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c
@@ -385,7 +385,21 @@ static u8 io_die_index_next;
 /* Lock to protect io_die_start, io_die_index_next */
 static DEFINE_MUTEX(domain_lock);
 
-static void set_domain_id(int id,  int num_resources,
+static void set_instance_id(int id, struct tpmi_uncore_cluster_info *cluster_info)
+{
+	/*
+	 * In its base form the domain_id is a per-TPMI device value that lists
+	 * feature instances for that specific TPMI device (instances as named by
+	 * the intel_vsec system). On newer platforms the cdie system comes into
+	 * effect which makes domain_id a unique identifier and there is no more
+	 * correlation between the TPMI device and the domain_id number. The old
+	 * version is still relevant so TPMI device scoped information can be
+	 * matched with the data from the TPMI driver.
+	 */
+	cluster_info->uncore_data.instance_id = id;
+}
+
+static void set_domain_id(int id, int num_resources,
 			  struct oobmsm_plat_info *plat_info,
 			  struct tpmi_uncore_cluster_info *cluster_info)
 {
@@ -686,6 +700,7 @@ static int uncore_probe(struct auxiliary_device *auxdev, const struct auxiliary_
 			set_cdie_id(i, cluster_info, plat_info);
 
 			set_domain_id(i, num_resources, plat_info, cluster_info);
+			set_instance_id(i, cluster_info);
 
 			cluster_info->uncore_root = tpmi_uncore;
 
-- 
2.53.0