[PATCH v2 12/17] firmware: arm_scmi: Add Telemetry components view

Cristian Marussi posted 17 patches 3 weeks, 5 days ago
[PATCH v2 12/17] firmware: arm_scmi: Add Telemetry components view
Posted by Cristian Marussi 3 weeks, 5 days ago
Add an alternative filesystem view for the discovered Data Events, where
the tree of DEs is laid out following the discovered topological order
instead of the existing flat layout.

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
v1 --> v2
 - Use new FS API
 - Introduce new stlmfs_lookup_by_name helper
---
 .../firmware/arm_scmi/scmi_system_telemetry.c | 684 ++++++++++++++++++
 1 file changed, 684 insertions(+)

diff --git a/drivers/firmware/arm_scmi/scmi_system_telemetry.c b/drivers/firmware/arm_scmi/scmi_system_telemetry.c
index 721de615bec3..1221520356fd 100644
--- a/drivers/firmware/arm_scmi/scmi_system_telemetry.c
+++ b/drivers/firmware/arm_scmi/scmi_system_telemetry.c
@@ -174,6 +174,7 @@ struct scmi_tlm_inode {
  * @top_dentry: A reference to the top dentry for this instance.
  * @des_dentry: A reference to the DES dentry for this instance.
  * @grps_dentry: A reference to the groups dentry for this instance.
+ * @compo_dentry: A reference to the components dentry for this instance.
  * @info: A handy reference to this instance SCMI Telemetry info data.
  *
  */
@@ -188,6 +189,7 @@ struct scmi_tlm_instance {
 	struct dentry *top_dentry;
 	struct dentry *des_dentry;
 	struct dentry *grps_dentry;
+	struct dentry *compo_dentry;
 	const struct scmi_telemetry_info *info;
 };
 
@@ -196,6 +198,526 @@ static int scmi_telemetry_instance_register(struct super_block *sb,
 
 static LIST_HEAD(scmi_telemetry_instances);
 
+#define TYPES_ARRAY_SZ		256
+
+static const char *compo_types[TYPES_ARRAY_SZ] = {
+	"unspec",
+	"cpu",
+	"cluster",
+	"gpu",
+	"npu",
+	"interconnnect",
+	"mem_cntrl",
+	"l1_cache",
+	"l2_cache",
+	"l3_cache",
+	"ll_cache",
+	"sys_cache",
+	"disp_cntrl",
+	"ipu",
+	"chiplet",
+	"package",
+	"soc",
+	"system",
+	"smcu",
+	"accel",
+	"battery",
+	"charger",
+	"pmic",
+	"board",
+	"memory",
+	"periph",
+	"periph_subc",
+	"lid",
+	"display",
+	"res_29",
+	"res_30",
+	"res_31",
+	"res_32",
+	"res_33",
+	"res_34",
+	"res_35",
+	"res_36",
+	"res_37",
+	"res_38",
+	"res_39",
+	"res_40",
+	"res_41",
+	"res_42",
+	"res_43",
+	"res_44",
+	"res_45",
+	"res_46",
+	"res_47",
+	"res_48",
+	"res_49",
+	"res_50",
+	"res_51",
+	"res_52",
+	"res_53",
+	"res_54",
+	"res_55",
+	"res_56",
+	"res_57",
+	"res_58",
+	"res_59",
+	"res_60",
+	"res_61",
+	"res_62",
+	"res_63",
+	"res_64",
+	"res_65",
+	"res_66",
+	"res_67",
+	"res_68",
+	"res_69",
+	"res_70",
+	"res_71",
+	"res_72",
+	"res_73",
+	"res_74",
+	"res_75",
+	"res_76",
+	"res_77",
+	"res_78",
+	"res_79",
+	"res_80",
+	"res_81",
+	"res_82",
+	"res_83",
+	"res_84",
+	"res_85",
+	"res_86",
+	"res_87",
+	"res_88",
+	"res_89",
+	"res_90",
+	"res_91",
+	"res_92",
+	"res_93",
+	"res_94",
+	"res_95",
+	"res_96",
+	"res_97",
+	"res_98",
+	"res_99",
+	"res_100",
+	"res_101",
+	"res_102",
+	"res_103",
+	"res_104",
+	"res_105",
+	"res_106",
+	"res_107",
+	"res_108",
+	"res_109",
+	"res_110",
+	"res_111",
+	"res_112",
+	"res_113",
+	"res_114",
+	"res_115",
+	"res_116",
+	"res_117",
+	"res_118",
+	"res_119",
+	"res_120",
+	"res_121",
+	"res_122",
+	"res_123",
+	"res_124",
+	"res_125",
+	"res_126",
+	"res_127",
+	"res_128",
+	"res_129",
+	"res_130",
+	"res_131",
+	"res_132",
+	"res_133",
+	"res_134",
+	"res_135",
+	"res_136",
+	"res_137",
+	"res_138",
+	"res_139",
+	"res_140",
+	"res_141",
+	"res_142",
+	"res_143",
+	"res_144",
+	"res_145",
+	"res_146",
+	"res_147",
+	"res_148",
+	"res_149",
+	"res_150",
+	"res_151",
+	"res_152",
+	"res_153",
+	"res_154",
+	"res_155",
+	"res_156",
+	"res_157",
+	"res_158",
+	"res_159",
+	"res_160",
+	"res_161",
+	"res_162",
+	"res_163",
+	"res_164",
+	"res_165",
+	"res_166",
+	"res_167",
+	"res_168",
+	"res_169",
+	"res_170",
+	"res_171",
+	"res_172",
+	"res_173",
+	"res_174",
+	"res_175",
+	"res_176",
+	"res_177",
+	"res_178",
+	"res_179",
+	"res_180",
+	"res_181",
+	"res_182",
+	"res_183",
+	"res_184",
+	"res_185",
+	"res_186",
+	"res_187",
+	"res_188",
+	"res_189",
+	"res_190",
+	"res_191",
+	"res_192",
+	"res_193",
+	"res_194",
+	"res_195",
+	"res_196",
+	"res_197",
+	"res_198",
+	"res_199",
+	"res_200",
+	"res_201",
+	"res_202",
+	"res_203",
+	"res_204",
+	"res_205",
+	"res_206",
+	"res_207",
+	"res_208",
+	"res_209",
+	"res_210",
+	"res_211",
+	"res_212",
+	"res_213",
+	"res_214",
+	"res_215",
+	"res_216",
+	"res_217",
+	"res_218",
+	"res_219",
+	"res_220",
+	"res_221",
+	"res_222",
+	"res_223",
+	"oem_224",
+	"oem_225",
+	"oem_226",
+	"oem_227",
+	"oem_228",
+	"oem_229",
+	"oem_230",
+	"oem_231",
+	"oem_232",
+	"oem_233",
+	"oem_234",
+	"oem_235",
+	"oem_236",
+	"oem_237",
+	"oem_238",
+	"oem_239",
+	"oem_240",
+	"oem_241",
+	"oem_242",
+	"oem_243",
+	"oem_244",
+	"oem_245",
+	"oem_246",
+	"oem_247",
+	"oem_248",
+	"oem_249",
+	"oem_250",
+	"oem_251",
+	"oem_252",
+	"oem_253",
+	"oem_254",
+	"oem_255",
+};
+
+static const char *unit_types[TYPES_ARRAY_SZ] = {
+	"none",
+	"unspec",
+	"celsius",
+	"fahrenheit",
+	"kelvin",
+	"volts",
+	"amps",
+	"watts",
+	"joules",
+	"coulombs",
+	"va",
+	"nits",
+	"lumens",
+	"lux",
+	"candelas",
+	"kpa",
+	"psi",
+	"newtons",
+	"cfm",
+	"rpm",
+	"hertz",
+	"seconds",
+	"minutes",
+	"hours",
+	"days",
+	"weeks",
+	"mils",
+	"inches",
+	"feet",
+	"cubic_inches",
+	"cubic_feet",
+	"meters",
+	"cubic_centimeters",
+	"cubic_meters",
+	"liters",
+	"fluid_ounces",
+	"radians",
+	"steradians",
+	"revolutions",
+	"cycles",
+	"gravities",
+	"ounces",
+	"pounds",
+	"foot_pounds",
+	"ounce_inches",
+	"gauss",
+	"gilberts",
+	"henries",
+	"farads",
+	"ohms",
+	"siemens",
+	"moles",
+	"becquerels",
+	"ppm",
+	"decibels",
+	"dba",
+	"dbc",
+	"grays",
+	"sieverts",
+	"color_temp_kelvin",
+	"bits",
+	"bytes",
+	"words",
+	"dwords",
+	"qwords",
+	"percentage",
+	"pascals",
+	"counts",
+	"grams",
+	"newton_meters",
+	"hits",
+	"misses",
+	"retries",
+	"overruns",
+	"underruns",
+	"collisions",
+	"packets",
+	"messages",
+	"chars",
+	"errors",
+	"corrected_err",
+	"uncorrectable_err",
+	"square_mils",
+	"square_inches",
+	"square_feet",
+	"square_centimeters",
+	"square_meters",
+	"radians_per_secs",
+	"beats_per_minute",
+	"meters_per_secs_squared",
+	"meters_per_secs",
+	"cubic_meter_per_secs",
+	"millimeters_mercury",
+	"radians_per_secs_squared",
+	"state",
+	"bps",
+	"res_96",
+	"res_97",
+	"res_98",
+	"res_99",
+	"res_100",
+	"res_101",
+	"res_102",
+	"res_103",
+	"res_104",
+	"res_105",
+	"res_106",
+	"res_107",
+	"res_108",
+	"res_109",
+	"res_110",
+	"res_111",
+	"res_112",
+	"res_113",
+	"res_114",
+	"res_115",
+	"res_116",
+	"res_117",
+	"res_118",
+	"res_119",
+	"res_120",
+	"res_121",
+	"res_122",
+	"res_123",
+	"res_124",
+	"res_125",
+	"res_126",
+	"res_127",
+	"res_128",
+	"res_129",
+	"res_130",
+	"res_131",
+	"res_132",
+	"res_133",
+	"res_134",
+	"res_135",
+	"res_136",
+	"res_137",
+	"res_138",
+	"res_139",
+	"res_140",
+	"res_141",
+	"res_142",
+	"res_143",
+	"res_144",
+	"res_145",
+	"res_146",
+	"res_147",
+	"res_148",
+	"res_149",
+	"res_150",
+	"res_151",
+	"res_152",
+	"res_153",
+	"res_154",
+	"res_155",
+	"res_156",
+	"res_157",
+	"res_158",
+	"res_159",
+	"res_160",
+	"res_161",
+	"res_162",
+	"res_163",
+	"res_164",
+	"res_165",
+	"res_166",
+	"res_167",
+	"res_168",
+	"res_169",
+	"res_170",
+	"res_171",
+	"res_172",
+	"res_173",
+	"res_174",
+	"res_175",
+	"res_176",
+	"res_177",
+	"res_178",
+	"res_179",
+	"res_180",
+	"res_181",
+	"res_182",
+	"res_183",
+	"res_184",
+	"res_185",
+	"res_186",
+	"res_187",
+	"res_188",
+	"res_189",
+	"res_190",
+	"res_191",
+	"res_192",
+	"res_193",
+	"res_194",
+	"res_195",
+	"res_196",
+	"res_197",
+	"res_198",
+	"res_199",
+	"res_200",
+	"res_201",
+	"res_202",
+	"res_203",
+	"res_204",
+	"res_205",
+	"res_206",
+	"res_207",
+	"res_208",
+	"res_209",
+	"res_210",
+	"res_211",
+	"res_212",
+	"res_213",
+	"res_214",
+	"res_215",
+	"res_216",
+	"res_217",
+	"res_218",
+	"res_219",
+	"res_220",
+	"res_221",
+	"res_222",
+	"res_223",
+	"res_224",
+	"res_225",
+	"res_226",
+	"res_227",
+	"res_228",
+	"res_229",
+	"res_230",
+	"res_231",
+	"res_232",
+	"res_233",
+	"res_234",
+	"res_235",
+	"res_236",
+	"res_237",
+	"res_238",
+	"res_239",
+	"res_240",
+	"res_241",
+	"res_242",
+	"res_243",
+	"res_244",
+	"res_245",
+	"res_246",
+	"res_247",
+	"res_248",
+	"res_249",
+	"res_250",
+	"res_251",
+	"res_252",
+	"res_253",
+	"res_254",
+	"oem_unit",
+};
+
 static struct inode *stlmfs_get_inode(struct super_block *sb)
 {
 	struct inode *inode = new_inode(sb);
@@ -815,6 +1337,18 @@ DEFINE_TLM_CLASS(persistent_tlmo, "persistent", 0,
 DEFINE_TLM_CLASS(value_tlmo, "value", 0,
 		 S_IFREG | S_IRUSR, &de_read_fops, NULL);
 
+static inline struct dentry *
+stlmfs_lookup_by_name(struct dentry *parent, const char *dname)
+{
+	struct qstr qstr;
+
+	qstr.name = dname;
+	qstr.len = strlen(dname);
+	qstr.hash = full_name_hash(parent, qstr.name, qstr.len);
+
+	return d_lookup(parent, &qstr);
+}
+
 static int scmi_telemetry_de_populate(struct super_block *sb,
 				      struct scmi_tlm_setup *tsp,
 				      struct dentry *parent,
@@ -1659,6 +2193,150 @@ static struct dentry *stlmfs_create_root_dentry(struct super_block *sb)
 	return dentry;
 }
 
+static int scmi_telemetry_de_subdir_symlink(struct super_block *sb,
+					    struct scmi_tlm_setup *tsp,
+					    const struct scmi_telemetry_de *de,
+					    struct dentry *parent)
+{
+	struct dentry *dentry;
+	struct inode *inode;
+	int ret;
+
+	if (IS_ERR(parent))
+		return 0;
+
+	char *name __free(kfree) = kasprintf(GFP_KERNEL, "0x%08X", de->info->id);
+	if (!name)
+		return -ENOMEM;
+
+	char *link __free(kfree) =
+		kasprintf(GFP_KERNEL, "../../../../../des/0x%08X", de->info->id);
+	if (!link)
+		return -ENOMEM;
+
+	dentry = simple_start_creating(parent, name);
+	if (IS_ERR(dentry))
+		return PTR_ERR(dentry);
+
+	inode = stlmfs_get_inode(sb);
+	if (unlikely(!inode)) {
+		dev_err(tsp->dev,
+			"out of free dentries, cannot create '%s'", name);
+		return stlmfs_failed_creating(dentry);
+	}
+
+	inode->i_mode = S_IFLNK | 0777;
+	inode->i_op = &simple_symlink_inode_operations;
+	inode_init_owner(&nop_mnt_idmap, inode, NULL, inode->i_mode);
+	inode->i_link = no_free_ptr(link);
+
+	//d_add(dentry, inode);
+	d_make_persistent(dentry, inode);
+
+	simple_done_creating(dentry);
+
+	return ret;
+}
+
+static struct dentry *
+scmi_telemetry_topology_path_get(struct super_block *sb,
+				 struct scmi_tlm_setup *tsp,
+				 struct dentry *parent, const char *dname)
+{
+	struct dentry *dentry;
+
+	dentry = stlmfs_lookup_by_name(parent, dname);
+	if (!dentry) {
+		struct scmi_tlm_class *dir_tlm_cls __free(kfree) =
+			kzalloc(sizeof(*dir_tlm_cls), GFP_KERNEL);
+		if (!dir_tlm_cls)
+			return NULL;
+
+		dir_tlm_cls->name = kasprintf(GFP_KERNEL, "%s", dname);
+		if (!dir_tlm_cls->name)
+			return NULL;
+
+		dir_tlm_cls->mode = S_IFDIR | S_IRWXU;
+		dir_tlm_cls->flags = TLM_IS_DYNAMIC;
+
+		dentry = stlmfs_create_dentry(sb, tsp, parent,
+					      dir_tlm_cls, NULL);
+		if (!IS_ERR(dentry))
+			retain_and_null_ptr(dir_tlm_cls);
+	}
+
+	return dentry;
+}
+
+static int scmi_telemetry_topology_add_node(struct super_block *sb,
+					    struct scmi_tlm_instance *ti,
+					    const struct scmi_telemetry_de *de)
+{
+	struct dentry *ctype, *cinst, *cunit, *dinst;
+	struct scmi_tlm_de_info *dei = de->info;
+	char inst_str[32];
+	int ret;
+
+	/* by_compo_type/<COMPO_TYPE_STR>/ */
+	ctype = scmi_telemetry_topology_path_get(sb, ti->tsp, ti->compo_dentry,
+						 compo_types[dei->compo_type]);
+	if (!ctype)
+		return -ENOMEM;
+
+	/* by_compo_type/<COMPO_TYPE_STR>/<N>/ */
+	snprintf(inst_str, 32, "%u", dei->compo_instance_id);
+	cinst = scmi_telemetry_topology_path_get(sb, ti->tsp, ctype, inst_str);
+	dput(ctype);
+	if (!cinst)
+		return -ENOMEM;
+
+	/* by_compo_type/<COMPO_TYPE_STR>/<N>/<DE_UNIT_TYPE_STR>/ */
+	cunit = scmi_telemetry_topology_path_get(sb, ti->tsp, cinst,
+						 unit_types[dei->unit]);
+	dput(cinst);
+	if (!cunit)
+		return -ENOMEM;
+
+	/* by_compo_type/<COMPO_TYPE_STR>/<N>/<DE_UNIT_TYPE_STR>/<N> */
+	snprintf(inst_str, 32, "%u", dei->instance_id);
+	dinst = scmi_telemetry_topology_path_get(sb, ti->tsp, cunit, inst_str);
+	dput(cunit);
+	if (!dinst)
+		return -ENOMEM;
+
+	ret = scmi_telemetry_de_subdir_symlink(sb, ti->tsp, de, dinst);
+	dput(dinst);
+
+	return ret;
+}
+
+DEFINE_TLM_CLASS(compo_dir_cls, "components", 0, S_IFDIR | S_IRWXU, NULL, NULL);
+
+static int scmi_telemetry_topology_view_add(struct scmi_tlm_instance *ti)
+{
+	const struct scmi_telemetry_res_info *rinfo;
+	struct scmi_tlm_setup *tsp = ti->tsp;
+	struct device *dev = tsp->dev;
+
+	rinfo = scmi_telemetry_res_info_get(tsp);
+	if (!rinfo || !rinfo->fully_enumerated)
+		return -ENODEV;
+
+	ti->compo_dentry =
+		stlmfs_create_dentry(ti->sb, tsp, ti->top_dentry, &compo_dir_cls, NULL);
+
+	for (int i = 0; i < rinfo->num_des; i++) {
+		int ret;
+
+		ret = scmi_telemetry_topology_add_node(ti->sb, ti, rinfo->des[i]);
+		if (ret)
+			dev_err(dev, "Fail to add node %s to topology. Skip.\n",
+				rinfo->des[i]->info->name);
+	}
+
+	return 0;
+}
+
 static int scmi_tlm_root_dentries_initialize(struct scmi_tlm_instance *ti)
 {
 	struct scmi_tlm_setup *tsp = ti->tsp;
@@ -1712,6 +2390,12 @@ static int scmi_telemetry_instance_register(struct super_block *sb,
 			 ti->top_cls.name);
 	}
 
+	ret = scmi_telemetry_topology_view_add(ti);
+	if (ret)
+		dev_warn(ti->tsp->dev,
+			 "Failed to create topology view for instance %s.\n",
+			 ti->top_cls.name);
+
 	return 0;
 }
 
-- 
2.52.0
Re: [PATCH v2 12/17] firmware: arm_scmi: Add Telemetry components view
Posted by Elif Topuz 3 weeks, 3 days ago
Hi Cristian,

On 14/01/2026 11:46, Cristian Marussi wrote:
> Add an alternative filesystem view for the discovered Data Events, where
> the tree of DEs is laid out following the discovered topological order
> instead of the existing flat layout.
> 
> Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
> ---
> v1 --> v2
>  - Use new FS API
>  - Introduce new stlmfs_lookup_by_name helper
> ---
>  .../firmware/arm_scmi/scmi_system_telemetry.c | 684 ++++++++++++++++++
>  1 file changed, 684 insertions(+)
> 
> diff --git a/drivers/firmware/arm_scmi/scmi_system_telemetry.c b/drivers/firmware/arm_scmi/scmi_system_telemetry.c
> index 721de615bec3..1221520356fd 100644
> --- a/drivers/firmware/arm_scmi/scmi_system_telemetry.c
> +++ b/drivers/firmware/arm_scmi/scmi_system_telemetry.c
> @@ -174,6 +174,7 @@ struct scmi_tlm_inode {
>   * @top_dentry: A reference to the top dentry for this instance.
>   * @des_dentry: A reference to the DES dentry for this instance.
>   * @grps_dentry: A reference to the groups dentry for this instance.
> + * @compo_dentry: A reference to the components dentry for this instance.
>   * @info: A handy reference to this instance SCMI Telemetry info data.
>   *
>   */
> @@ -188,6 +189,7 @@ struct scmi_tlm_instance {
>  	struct dentry *top_dentry;
>  	struct dentry *des_dentry;
>  	struct dentry *grps_dentry;
> +	struct dentry *compo_dentry;
>  	const struct scmi_telemetry_info *info;
>  };
>  
> @@ -196,6 +198,526 @@ static int scmi_telemetry_instance_register(struct super_block *sb,
>  
>  static LIST_HEAD(scmi_telemetry_instances);
>  
> +#define TYPES_ARRAY_SZ		256
> +
> +static const char *compo_types[TYPES_ARRAY_SZ] = {
> +	"unspec",
> +	"cpu",
> +	"cluster",
> +	"gpu",
> +	"npu",
> +	"interconnnect",
> +	"mem_cntrl",
> +	"l1_cache",
> +	"l2_cache",
> +	"l3_cache",
> +	"ll_cache",
> +	"sys_cache",
> +	"disp_cntrl",
> +	"ipu",
> +	"chiplet",
> +	"package",
> +	"soc",
> +	"system",
> +	"smcu",
> +	"accel",
> +	"battery",
> +	"charger",
> +	"pmic",
> +	"board",
> +	"memory",
> +	"periph",
> +	"periph_subc",
> +	"lid",
> +	"display",
> +	"res_29",
> +	"res_30",
> +	"res_31",
> +	"res_32",
> +	"res_33",
> +	"res_34",
> +	"res_35",
> +	"res_36",
> +	"res_37",
> +	"res_38",
> +	"res_39",
> +	"res_40",
> +	"res_41",
> +	"res_42",
> +	"res_43",
> +	"res_44",
> +	"res_45",
> +	"res_46",
> +	"res_47",
> +	"res_48",
> +	"res_49",
> +	"res_50",
> +	"res_51",
> +	"res_52",
> +	"res_53",
> +	"res_54",
> +	"res_55",
> +	"res_56",
> +	"res_57",
> +	"res_58",
> +	"res_59",
> +	"res_60",
> +	"res_61",
> +	"res_62",
> +	"res_63",
> +	"res_64",
> +	"res_65",
> +	"res_66",
> +	"res_67",
> +	"res_68",
> +	"res_69",
> +	"res_70",
> +	"res_71",
> +	"res_72",
> +	"res_73",
> +	"res_74",
> +	"res_75",
> +	"res_76",
> +	"res_77",
> +	"res_78",
> +	"res_79",
> +	"res_80",
> +	"res_81",
> +	"res_82",
> +	"res_83",
> +	"res_84",
> +	"res_85",
> +	"res_86",
> +	"res_87",
> +	"res_88",
> +	"res_89",
> +	"res_90",
> +	"res_91",
> +	"res_92",
> +	"res_93",
> +	"res_94",
> +	"res_95",
> +	"res_96",
> +	"res_97",
> +	"res_98",
> +	"res_99",
> +	"res_100",
> +	"res_101",
> +	"res_102",
> +	"res_103",
> +	"res_104",
> +	"res_105",
> +	"res_106",
> +	"res_107",
> +	"res_108",
> +	"res_109",
> +	"res_110",
> +	"res_111",
> +	"res_112",
> +	"res_113",
> +	"res_114",
> +	"res_115",
> +	"res_116",
> +	"res_117",
> +	"res_118",
> +	"res_119",
> +	"res_120",
> +	"res_121",
> +	"res_122",
> +	"res_123",
> +	"res_124",
> +	"res_125",
> +	"res_126",
> +	"res_127",
> +	"res_128",
> +	"res_129",
> +	"res_130",
> +	"res_131",
> +	"res_132",
> +	"res_133",
> +	"res_134",
> +	"res_135",
> +	"res_136",
> +	"res_137",
> +	"res_138",
> +	"res_139",
> +	"res_140",
> +	"res_141",
> +	"res_142",
> +	"res_143",
> +	"res_144",
> +	"res_145",
> +	"res_146",
> +	"res_147",
> +	"res_148",
> +	"res_149",
> +	"res_150",
> +	"res_151",
> +	"res_152",
> +	"res_153",
> +	"res_154",
> +	"res_155",
> +	"res_156",
> +	"res_157",
> +	"res_158",
> +	"res_159",
> +	"res_160",
> +	"res_161",
> +	"res_162",
> +	"res_163",
> +	"res_164",
> +	"res_165",
> +	"res_166",
> +	"res_167",
> +	"res_168",
> +	"res_169",
> +	"res_170",
> +	"res_171",
> +	"res_172",
> +	"res_173",
> +	"res_174",
> +	"res_175",
> +	"res_176",
> +	"res_177",
> +	"res_178",
> +	"res_179",
> +	"res_180",
> +	"res_181",
> +	"res_182",
> +	"res_183",
> +	"res_184",
> +	"res_185",
> +	"res_186",
> +	"res_187",
> +	"res_188",
> +	"res_189",
> +	"res_190",
> +	"res_191",
> +	"res_192",
> +	"res_193",
> +	"res_194",
> +	"res_195",
> +	"res_196",
> +	"res_197",
> +	"res_198",
> +	"res_199",
> +	"res_200",
> +	"res_201",
> +	"res_202",
> +	"res_203",
> +	"res_204",
> +	"res_205",
> +	"res_206",
> +	"res_207",
> +	"res_208",
> +	"res_209",
> +	"res_210",
> +	"res_211",
> +	"res_212",
> +	"res_213",
> +	"res_214",
> +	"res_215",
> +	"res_216",
> +	"res_217",
> +	"res_218",
> +	"res_219",
> +	"res_220",
> +	"res_221",
> +	"res_222",
> +	"res_223",
> +	"oem_224",
> +	"oem_225",
> +	"oem_226",
> +	"oem_227",
> +	"oem_228",
> +	"oem_229",
> +	"oem_230",
> +	"oem_231",
> +	"oem_232",
> +	"oem_233",
> +	"oem_234",
> +	"oem_235",
> +	"oem_236",
> +	"oem_237",
> +	"oem_238",
> +	"oem_239",
> +	"oem_240",
> +	"oem_241",
> +	"oem_242",
> +	"oem_243",
> +	"oem_244",
> +	"oem_245",
> +	"oem_246",
> +	"oem_247",
> +	"oem_248",
> +	"oem_249",
> +	"oem_250",
> +	"oem_251",
> +	"oem_252",
> +	"oem_253",
> +	"oem_254",
> +	"oem_255",
> +};
> +
> +static const char *unit_types[TYPES_ARRAY_SZ] = {
> +	"none",
> +	"unspec",
> +	"celsius",
> +	"fahrenheit",
> +	"kelvin",
> +	"volts",
> +	"amps",
> +	"watts",
> +	"joules",
> +	"coulombs",
> +	"va",
> +	"nits",
> +	"lumens",
> +	"lux",
> +	"candelas",
> +	"kpa",
> +	"psi",
> +	"newtons",
> +	"cfm",
> +	"rpm",
> +	"hertz",
> +	"seconds",
> +	"minutes",
> +	"hours",
> +	"days",
> +	"weeks",
> +	"mils",
> +	"inches",
> +	"feet",
> +	"cubic_inches",
> +	"cubic_feet",
> +	"meters",
> +	"cubic_centimeters",
> +	"cubic_meters",
> +	"liters",
> +	"fluid_ounces",
> +	"radians",
> +	"steradians",
> +	"revolutions",
> +	"cycles",
> +	"gravities",
> +	"ounces",
> +	"pounds",
> +	"foot_pounds",
> +	"ounce_inches",
> +	"gauss",
> +	"gilberts",
> +	"henries",
> +	"farads",
> +	"ohms",
> +	"siemens",
> +	"moles",
> +	"becquerels",
> +	"ppm",
> +	"decibels",
> +	"dba",
> +	"dbc",
> +	"grays",
> +	"sieverts",
> +	"color_temp_kelvin",
> +	"bits",
> +	"bytes",
> +	"words",
> +	"dwords",
> +	"qwords",
> +	"percentage",
> +	"pascals",
> +	"counts",
> +	"grams",
> +	"newton_meters",
> +	"hits",
> +	"misses",
> +	"retries",
> +	"overruns",
> +	"underruns",
> +	"collisions",
> +	"packets",
> +	"messages",
> +	"chars",
> +	"errors",
> +	"corrected_err",
> +	"uncorrectable_err",
> +	"square_mils",
> +	"square_inches",
> +	"square_feet",
> +	"square_centimeters",
> +	"square_meters",
> +	"radians_per_secs",
> +	"beats_per_minute",
> +	"meters_per_secs_squared",
> +	"meters_per_secs",
> +	"cubic_meter_per_secs",
> +	"millimeters_mercury",
> +	"radians_per_secs_squared",
> +	"state",
> +	"bps",
> +	"res_96",
> +	"res_97",
> +	"res_98",
> +	"res_99",
> +	"res_100",
> +	"res_101",
> +	"res_102",
> +	"res_103",
> +	"res_104",
> +	"res_105",
> +	"res_106",
> +	"res_107",
> +	"res_108",
> +	"res_109",
> +	"res_110",
> +	"res_111",
> +	"res_112",
> +	"res_113",
> +	"res_114",
> +	"res_115",
> +	"res_116",
> +	"res_117",
> +	"res_118",
> +	"res_119",
> +	"res_120",
> +	"res_121",
> +	"res_122",
> +	"res_123",
> +	"res_124",
> +	"res_125",
> +	"res_126",
> +	"res_127",
> +	"res_128",
> +	"res_129",
> +	"res_130",
> +	"res_131",
> +	"res_132",
> +	"res_133",
> +	"res_134",
> +	"res_135",
> +	"res_136",
> +	"res_137",
> +	"res_138",
> +	"res_139",
> +	"res_140",
> +	"res_141",
> +	"res_142",
> +	"res_143",
> +	"res_144",
> +	"res_145",
> +	"res_146",
> +	"res_147",
> +	"res_148",
> +	"res_149",
> +	"res_150",
> +	"res_151",
> +	"res_152",
> +	"res_153",
> +	"res_154",
> +	"res_155",
> +	"res_156",
> +	"res_157",
> +	"res_158",
> +	"res_159",
> +	"res_160",
> +	"res_161",
> +	"res_162",
> +	"res_163",
> +	"res_164",
> +	"res_165",
> +	"res_166",
> +	"res_167",
> +	"res_168",
> +	"res_169",
> +	"res_170",
> +	"res_171",
> +	"res_172",
> +	"res_173",
> +	"res_174",
> +	"res_175",
> +	"res_176",
> +	"res_177",
> +	"res_178",
> +	"res_179",
> +	"res_180",
> +	"res_181",
> +	"res_182",
> +	"res_183",
> +	"res_184",
> +	"res_185",
> +	"res_186",
> +	"res_187",
> +	"res_188",
> +	"res_189",
> +	"res_190",
> +	"res_191",
> +	"res_192",
> +	"res_193",
> +	"res_194",
> +	"res_195",
> +	"res_196",
> +	"res_197",
> +	"res_198",
> +	"res_199",
> +	"res_200",
> +	"res_201",
> +	"res_202",
> +	"res_203",
> +	"res_204",
> +	"res_205",
> +	"res_206",
> +	"res_207",
> +	"res_208",
> +	"res_209",
> +	"res_210",
> +	"res_211",
> +	"res_212",
> +	"res_213",
> +	"res_214",
> +	"res_215",
> +	"res_216",
> +	"res_217",
> +	"res_218",
> +	"res_219",
> +	"res_220",
> +	"res_221",
> +	"res_222",
> +	"res_223",
> +	"res_224",
> +	"res_225",
> +	"res_226",
> +	"res_227",
> +	"res_228",
> +	"res_229",
> +	"res_230",
> +	"res_231",
> +	"res_232",
> +	"res_233",
> +	"res_234",
> +	"res_235",
> +	"res_236",
> +	"res_237",
> +	"res_238",
> +	"res_239",
> +	"res_240",
> +	"res_241",
> +	"res_242",
> +	"res_243",
> +	"res_244",
> +	"res_245",
> +	"res_246",
> +	"res_247",
> +	"res_248",
> +	"res_249",
> +	"res_250",
> +	"res_251",
> +	"res_252",
> +	"res_253",
> +	"res_254",
> +	"oem_unit",
> +};
> +
>  static struct inode *stlmfs_get_inode(struct super_block *sb)
>  {
>  	struct inode *inode = new_inode(sb);
> @@ -815,6 +1337,18 @@ DEFINE_TLM_CLASS(persistent_tlmo, "persistent", 0,
>  DEFINE_TLM_CLASS(value_tlmo, "value", 0,
>  		 S_IFREG | S_IRUSR, &de_read_fops, NULL);
>  
> +static inline struct dentry *
> +stlmfs_lookup_by_name(struct dentry *parent, const char *dname)
> +{
> +	struct qstr qstr;
> +
> +	qstr.name = dname;
> +	qstr.len = strlen(dname);
> +	qstr.hash = full_name_hash(parent, qstr.name, qstr.len);
> +
> +	return d_lookup(parent, &qstr);
> +}
> +
>  static int scmi_telemetry_de_populate(struct super_block *sb,
>  				      struct scmi_tlm_setup *tsp,
>  				      struct dentry *parent,
> @@ -1659,6 +2193,150 @@ static struct dentry *stlmfs_create_root_dentry(struct super_block *sb)
>  	return dentry;
>  }
>  
> +static int scmi_telemetry_de_subdir_symlink(struct super_block *sb,
> +					    struct scmi_tlm_setup *tsp,
> +					    const struct scmi_telemetry_de *de,
> +					    struct dentry *parent)
> +{
> +	struct dentry *dentry;
> +	struct inode *inode;
> +	int ret;
I notice that ret isn't assigned a value and the function returns ret without
initialising.

> +
> +	if (IS_ERR(parent))
> +		return 0;
> +
> +	char *name __free(kfree) = kasprintf(GFP_KERNEL, "0x%08X", de->info->id);
> +	if (!name)
> +		return -ENOMEM;
> +
> +	char *link __free(kfree) =
> +		kasprintf(GFP_KERNEL, "../../../../../des/0x%08X", de->info->id);
> +	if (!link)
> +		return -ENOMEM;
> +
> +	dentry = simple_start_creating(parent, name);
> +	if (IS_ERR(dentry))
> +		return PTR_ERR(dentry);
> +
> +	inode = stlmfs_get_inode(sb);
> +	if (unlikely(!inode)) {
> +		dev_err(tsp->dev,
> +			"out of free dentries, cannot create '%s'", name);
> +		return stlmfs_failed_creating(dentry);
> +	}
> +
> +	inode->i_mode = S_IFLNK | 0777;
> +	inode->i_op = &simple_symlink_inode_operations;
> +	inode_init_owner(&nop_mnt_idmap, inode, NULL, inode->i_mode);
> +	inode->i_link = no_free_ptr(link);
> +
> +	//d_add(dentry, inode);
> +	d_make_persistent(dentry, inode);
> +
> +	simple_done_creating(dentry);
> +
> +	return ret;
> +}
> +
> +static struct dentry *
> +scmi_telemetry_topology_path_get(struct super_block *sb,
> +				 struct scmi_tlm_setup *tsp,
> +				 struct dentry *parent, const char *dname)
> +{
> +	struct dentry *dentry;
> +
> +	dentry = stlmfs_lookup_by_name(parent, dname);
> +	if (!dentry) {
> +		struct scmi_tlm_class *dir_tlm_cls __free(kfree) =
> +			kzalloc(sizeof(*dir_tlm_cls), GFP_KERNEL);
> +		if (!dir_tlm_cls)
> +			return NULL;
> +
> +		dir_tlm_cls->name = kasprintf(GFP_KERNEL, "%s", dname);
> +		if (!dir_tlm_cls->name)
> +			return NULL;
> +
> +		dir_tlm_cls->mode = S_IFDIR | S_IRWXU;
> +		dir_tlm_cls->flags = TLM_IS_DYNAMIC;
> +
> +		dentry = stlmfs_create_dentry(sb, tsp, parent,
> +					      dir_tlm_cls, NULL);
> +		if (!IS_ERR(dentry))
> +			retain_and_null_ptr(dir_tlm_cls);
> +	}
> +
> +	return dentry;
> +}
> +
> +static int scmi_telemetry_topology_add_node(struct super_block *sb,
> +					    struct scmi_tlm_instance *ti,
> +					    const struct scmi_telemetry_de *de)
> +{
> +	struct dentry *ctype, *cinst, *cunit, *dinst;
> +	struct scmi_tlm_de_info *dei = de->info;
> +	char inst_str[32];
> +	int ret;
> +
> +	/* by_compo_type/<COMPO_TYPE_STR>/ */
> +	ctype = scmi_telemetry_topology_path_get(sb, ti->tsp, ti->compo_dentry,
> +						 compo_types[dei->compo_type]);
> +	if (!ctype)
> +		return -ENOMEM;
> +
> +	/* by_compo_type/<COMPO_TYPE_STR>/<N>/ */
> +	snprintf(inst_str, 32, "%u", dei->compo_instance_id);
> +	cinst = scmi_telemetry_topology_path_get(sb, ti->tsp, ctype, inst_str);
> +	dput(ctype);
> +	if (!cinst)
> +		return -ENOMEM;
> +
> +	/* by_compo_type/<COMPO_TYPE_STR>/<N>/<DE_UNIT_TYPE_STR>/ */
> +	cunit = scmi_telemetry_topology_path_get(sb, ti->tsp, cinst,
> +						 unit_types[dei->unit]);
> +	dput(cinst);
> +	if (!cunit)
> +		return -ENOMEM;
> +
> +	/* by_compo_type/<COMPO_TYPE_STR>/<N>/<DE_UNIT_TYPE_STR>/<N> */
> +	snprintf(inst_str, 32, "%u", dei->instance_id);
> +	dinst = scmi_telemetry_topology_path_get(sb, ti->tsp, cunit, inst_str);
> +	dput(cunit);
> +	if (!dinst)
> +		return -ENOMEM;
> +
> +	ret = scmi_telemetry_de_subdir_symlink(sb, ti->tsp, de, dinst);
> +	dput(dinst);
> +
> +	return ret;
> +}
> +
> +DEFINE_TLM_CLASS(compo_dir_cls, "components", 0, S_IFDIR | S_IRWXU, NULL, NULL);
> +
> +static int scmi_telemetry_topology_view_add(struct scmi_tlm_instance *ti)
> +{
> +	const struct scmi_telemetry_res_info *rinfo;
> +	struct scmi_tlm_setup *tsp = ti->tsp;
> +	struct device *dev = tsp->dev;
> +
> +	rinfo = scmi_telemetry_res_info_get(tsp);
> +	if (!rinfo || !rinfo->fully_enumerated)
> +		return -ENODEV;
> +
> +	ti->compo_dentry =
> +		stlmfs_create_dentry(ti->sb, tsp, ti->top_dentry, &compo_dir_cls, NULL);
> +
> +	for (int i = 0; i < rinfo->num_des; i++) {
> +		int ret;
> +
> +		ret = scmi_telemetry_topology_add_node(ti->sb, ti, rinfo->des[i]);
> +		if (ret)
> +			dev_err(dev, "Fail to add node %s to topology. Skip.\n",
> +				rinfo->des[i]->info->name);
> +	}
> +
> +	return 0;
> +}
> +
>  static int scmi_tlm_root_dentries_initialize(struct scmi_tlm_instance *ti)
>  {
>  	struct scmi_tlm_setup *tsp = ti->tsp;
> @@ -1712,6 +2390,12 @@ static int scmi_telemetry_instance_register(struct super_block *sb,
>  			 ti->top_cls.name);
>  	}
>  
> +	ret = scmi_telemetry_topology_view_add(ti);
> +	if (ret)
> +		dev_warn(ti->tsp->dev,
> +			 "Failed to create topology view for instance %s.\n",
> +			 ti->top_cls.name);
> +
>  	return 0;
>  }
>  

I will continue reviewing,
Thanks,
Elif
Re: [PATCH v2 12/17] firmware: arm_scmi: Add Telemetry components view
Posted by Cristian Marussi 3 weeks ago
On Fri, Jan 16, 2026 at 01:35:00PM +0000, Elif Topuz wrote:
> 
> Hi Cristian,

H Elif,

> 
> On 14/01/2026 11:46, Cristian Marussi wrote:
> > Add an alternative filesystem view for the discovered Data Events, where
> > the tree of DEs is laid out following the discovered topological order
> > instead of the existing flat layout.
> > 
> > Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
> > ---
> > v1 --> v2
> >  - Use new FS API
> >  - Introduce new stlmfs_lookup_by_name helper
> > ---
> >  .../firmware/arm_scmi/scmi_system_telemetry.c | 684 ++++++++++++++++++
> >  1 file changed, 684 insertions(+)
> > 
> > diff --git a/drivers/firmware/arm_scmi/scmi_system_telemetry.c b/drivers/firmware/arm_scmi/scmi_system_telemetry.c
> > index 721de615bec3..1221520356fd 100644
> > --- a/drivers/firmware/arm_scmi/scmi_system_telemetry.c
> > +++ b/drivers/firmware/arm_scmi/scmi_system_telemetry.c
> > @@ -174,6 +174,7 @@ struct scmi_tlm_inode {
> >   * @top_dentry: A reference to the top dentry for this instance.
> >   * @des_dentry: A reference to the DES dentry for this instance.
> >   * @grps_dentry: A reference to the groups dentry for this instance.
> > + * @compo_dentry: A reference to the components dentry for this instance.
> >   * @info: A handy reference to this instance SCMI Telemetry info data.
> >   *
> >   */
> > @@ -188,6 +189,7 @@ struct scmi_tlm_instance {
> >  	struct dentry *top_dentry;
> >  	struct dentry *des_dentry;
> >  	struct dentry *grps_dentry;
> > +	struct dentry *compo_dentry;
> >  	const struct scmi_telemetry_info *info;
> >  };
> >  
> > @@ -196,6 +198,526 @@ static int scmi_telemetry_instance_register(struct super_block *sb,
> >  
> >  static LIST_HEAD(scmi_telemetry_instances);
> >  
> > +#define TYPES_ARRAY_SZ		256
> > +
> > +static const char *compo_types[TYPES_ARRAY_SZ] = {
> > +	"unspec",
> > +	"cpu",
> > +	"cluster",
> > +	"gpu",
> > +	"npu",
> > +	"interconnnect",
> > +	"mem_cntrl",
> > +	"l1_cache",
> > +	"l2_cache",
> > +	"l3_cache",
> > +	"ll_cache",
> > +	"sys_cache",
> > +	"disp_cntrl",
> > +	"ipu",
> > +	"chiplet",
> > +	"package",
> > +	"soc",
> > +	"system",
> > +	"smcu",
> > +	"accel",
> > +	"battery",
> > +	"charger",
> > +	"pmic",
> > +	"board",
> > +	"memory",
> > +	"periph",
> > +	"periph_subc",
> > +	"lid",
> > +	"display",
> > +	"res_29",
> > +	"res_30",
> > +	"res_31",
> > +	"res_32",
> > +	"res_33",
> > +	"res_34",
> > +	"res_35",
> > +	"res_36",
> > +	"res_37",
> > +	"res_38",
> > +	"res_39",
> > +	"res_40",
> > +	"res_41",
> > +	"res_42",
> > +	"res_43",
> > +	"res_44",
> > +	"res_45",
> > +	"res_46",
> > +	"res_47",
> > +	"res_48",
> > +	"res_49",
> > +	"res_50",
> > +	"res_51",
> > +	"res_52",
> > +	"res_53",
> > +	"res_54",
> > +	"res_55",
> > +	"res_56",
> > +	"res_57",
> > +	"res_58",
> > +	"res_59",
> > +	"res_60",
> > +	"res_61",
> > +	"res_62",
> > +	"res_63",
> > +	"res_64",
> > +	"res_65",
> > +	"res_66",
> > +	"res_67",
> > +	"res_68",
> > +	"res_69",
> > +	"res_70",
> > +	"res_71",
> > +	"res_72",
> > +	"res_73",
> > +	"res_74",
> > +	"res_75",
> > +	"res_76",
> > +	"res_77",
> > +	"res_78",
> > +	"res_79",
> > +	"res_80",
> > +	"res_81",
> > +	"res_82",
> > +	"res_83",
> > +	"res_84",
> > +	"res_85",
> > +	"res_86",
> > +	"res_87",
> > +	"res_88",
> > +	"res_89",
> > +	"res_90",
> > +	"res_91",
> > +	"res_92",
> > +	"res_93",
> > +	"res_94",
> > +	"res_95",
> > +	"res_96",
> > +	"res_97",
> > +	"res_98",
> > +	"res_99",
> > +	"res_100",
> > +	"res_101",
> > +	"res_102",
> > +	"res_103",
> > +	"res_104",
> > +	"res_105",
> > +	"res_106",
> > +	"res_107",
> > +	"res_108",
> > +	"res_109",
> > +	"res_110",
> > +	"res_111",
> > +	"res_112",
> > +	"res_113",
> > +	"res_114",
> > +	"res_115",
> > +	"res_116",
> > +	"res_117",
> > +	"res_118",
> > +	"res_119",
> > +	"res_120",
> > +	"res_121",
> > +	"res_122",
> > +	"res_123",
> > +	"res_124",
> > +	"res_125",
> > +	"res_126",
> > +	"res_127",
> > +	"res_128",
> > +	"res_129",
> > +	"res_130",
> > +	"res_131",
> > +	"res_132",
> > +	"res_133",
> > +	"res_134",
> > +	"res_135",
> > +	"res_136",
> > +	"res_137",
> > +	"res_138",
> > +	"res_139",
> > +	"res_140",
> > +	"res_141",
> > +	"res_142",
> > +	"res_143",
> > +	"res_144",
> > +	"res_145",
> > +	"res_146",
> > +	"res_147",
> > +	"res_148",
> > +	"res_149",
> > +	"res_150",
> > +	"res_151",
> > +	"res_152",
> > +	"res_153",
> > +	"res_154",
> > +	"res_155",
> > +	"res_156",
> > +	"res_157",
> > +	"res_158",
> > +	"res_159",
> > +	"res_160",
> > +	"res_161",
> > +	"res_162",
> > +	"res_163",
> > +	"res_164",
> > +	"res_165",
> > +	"res_166",
> > +	"res_167",
> > +	"res_168",
> > +	"res_169",
> > +	"res_170",
> > +	"res_171",
> > +	"res_172",
> > +	"res_173",
> > +	"res_174",
> > +	"res_175",
> > +	"res_176",
> > +	"res_177",
> > +	"res_178",
> > +	"res_179",
> > +	"res_180",
> > +	"res_181",
> > +	"res_182",
> > +	"res_183",
> > +	"res_184",
> > +	"res_185",
> > +	"res_186",
> > +	"res_187",
> > +	"res_188",
> > +	"res_189",
> > +	"res_190",
> > +	"res_191",
> > +	"res_192",
> > +	"res_193",
> > +	"res_194",
> > +	"res_195",
> > +	"res_196",
> > +	"res_197",
> > +	"res_198",
> > +	"res_199",
> > +	"res_200",
> > +	"res_201",
> > +	"res_202",
> > +	"res_203",
> > +	"res_204",
> > +	"res_205",
> > +	"res_206",
> > +	"res_207",
> > +	"res_208",
> > +	"res_209",
> > +	"res_210",
> > +	"res_211",
> > +	"res_212",
> > +	"res_213",
> > +	"res_214",
> > +	"res_215",
> > +	"res_216",
> > +	"res_217",
> > +	"res_218",
> > +	"res_219",
> > +	"res_220",
> > +	"res_221",
> > +	"res_222",
> > +	"res_223",
> > +	"oem_224",
> > +	"oem_225",
> > +	"oem_226",
> > +	"oem_227",
> > +	"oem_228",
> > +	"oem_229",
> > +	"oem_230",
> > +	"oem_231",
> > +	"oem_232",
> > +	"oem_233",
> > +	"oem_234",
> > +	"oem_235",
> > +	"oem_236",
> > +	"oem_237",
> > +	"oem_238",
> > +	"oem_239",
> > +	"oem_240",
> > +	"oem_241",
> > +	"oem_242",
> > +	"oem_243",
> > +	"oem_244",
> > +	"oem_245",
> > +	"oem_246",
> > +	"oem_247",
> > +	"oem_248",
> > +	"oem_249",
> > +	"oem_250",
> > +	"oem_251",
> > +	"oem_252",
> > +	"oem_253",
> > +	"oem_254",
> > +	"oem_255",
> > +};
> > +
> > +static const char *unit_types[TYPES_ARRAY_SZ] = {
> > +	"none",
> > +	"unspec",
> > +	"celsius",
> > +	"fahrenheit",
> > +	"kelvin",
> > +	"volts",
> > +	"amps",
> > +	"watts",
> > +	"joules",
> > +	"coulombs",
> > +	"va",
> > +	"nits",
> > +	"lumens",
> > +	"lux",
> > +	"candelas",
> > +	"kpa",
> > +	"psi",
> > +	"newtons",
> > +	"cfm",
> > +	"rpm",
> > +	"hertz",
> > +	"seconds",
> > +	"minutes",
> > +	"hours",
> > +	"days",
> > +	"weeks",
> > +	"mils",
> > +	"inches",
> > +	"feet",
> > +	"cubic_inches",
> > +	"cubic_feet",
> > +	"meters",
> > +	"cubic_centimeters",
> > +	"cubic_meters",
> > +	"liters",
> > +	"fluid_ounces",
> > +	"radians",
> > +	"steradians",
> > +	"revolutions",
> > +	"cycles",
> > +	"gravities",
> > +	"ounces",
> > +	"pounds",
> > +	"foot_pounds",
> > +	"ounce_inches",
> > +	"gauss",
> > +	"gilberts",
> > +	"henries",
> > +	"farads",
> > +	"ohms",
> > +	"siemens",
> > +	"moles",
> > +	"becquerels",
> > +	"ppm",
> > +	"decibels",
> > +	"dba",
> > +	"dbc",
> > +	"grays",
> > +	"sieverts",
> > +	"color_temp_kelvin",
> > +	"bits",
> > +	"bytes",
> > +	"words",
> > +	"dwords",
> > +	"qwords",
> > +	"percentage",
> > +	"pascals",
> > +	"counts",
> > +	"grams",
> > +	"newton_meters",
> > +	"hits",
> > +	"misses",
> > +	"retries",
> > +	"overruns",
> > +	"underruns",
> > +	"collisions",
> > +	"packets",
> > +	"messages",
> > +	"chars",
> > +	"errors",
> > +	"corrected_err",
> > +	"uncorrectable_err",
> > +	"square_mils",
> > +	"square_inches",
> > +	"square_feet",
> > +	"square_centimeters",
> > +	"square_meters",
> > +	"radians_per_secs",
> > +	"beats_per_minute",
> > +	"meters_per_secs_squared",
> > +	"meters_per_secs",
> > +	"cubic_meter_per_secs",
> > +	"millimeters_mercury",
> > +	"radians_per_secs_squared",
> > +	"state",
> > +	"bps",
> > +	"res_96",
> > +	"res_97",
> > +	"res_98",
> > +	"res_99",
> > +	"res_100",
> > +	"res_101",
> > +	"res_102",
> > +	"res_103",
> > +	"res_104",
> > +	"res_105",
> > +	"res_106",
> > +	"res_107",
> > +	"res_108",
> > +	"res_109",
> > +	"res_110",
> > +	"res_111",
> > +	"res_112",
> > +	"res_113",
> > +	"res_114",
> > +	"res_115",
> > +	"res_116",
> > +	"res_117",
> > +	"res_118",
> > +	"res_119",
> > +	"res_120",
> > +	"res_121",
> > +	"res_122",
> > +	"res_123",
> > +	"res_124",
> > +	"res_125",
> > +	"res_126",
> > +	"res_127",
> > +	"res_128",
> > +	"res_129",
> > +	"res_130",
> > +	"res_131",
> > +	"res_132",
> > +	"res_133",
> > +	"res_134",
> > +	"res_135",
> > +	"res_136",
> > +	"res_137",
> > +	"res_138",
> > +	"res_139",
> > +	"res_140",
> > +	"res_141",
> > +	"res_142",
> > +	"res_143",
> > +	"res_144",
> > +	"res_145",
> > +	"res_146",
> > +	"res_147",
> > +	"res_148",
> > +	"res_149",
> > +	"res_150",
> > +	"res_151",
> > +	"res_152",
> > +	"res_153",
> > +	"res_154",
> > +	"res_155",
> > +	"res_156",
> > +	"res_157",
> > +	"res_158",
> > +	"res_159",
> > +	"res_160",
> > +	"res_161",
> > +	"res_162",
> > +	"res_163",
> > +	"res_164",
> > +	"res_165",
> > +	"res_166",
> > +	"res_167",
> > +	"res_168",
> > +	"res_169",
> > +	"res_170",
> > +	"res_171",
> > +	"res_172",
> > +	"res_173",
> > +	"res_174",
> > +	"res_175",
> > +	"res_176",
> > +	"res_177",
> > +	"res_178",
> > +	"res_179",
> > +	"res_180",
> > +	"res_181",
> > +	"res_182",
> > +	"res_183",
> > +	"res_184",
> > +	"res_185",
> > +	"res_186",
> > +	"res_187",
> > +	"res_188",
> > +	"res_189",
> > +	"res_190",
> > +	"res_191",
> > +	"res_192",
> > +	"res_193",
> > +	"res_194",
> > +	"res_195",
> > +	"res_196",
> > +	"res_197",
> > +	"res_198",
> > +	"res_199",
> > +	"res_200",
> > +	"res_201",
> > +	"res_202",
> > +	"res_203",
> > +	"res_204",
> > +	"res_205",
> > +	"res_206",
> > +	"res_207",
> > +	"res_208",
> > +	"res_209",
> > +	"res_210",
> > +	"res_211",
> > +	"res_212",
> > +	"res_213",
> > +	"res_214",
> > +	"res_215",
> > +	"res_216",
> > +	"res_217",
> > +	"res_218",
> > +	"res_219",
> > +	"res_220",
> > +	"res_221",
> > +	"res_222",
> > +	"res_223",
> > +	"res_224",
> > +	"res_225",
> > +	"res_226",
> > +	"res_227",
> > +	"res_228",
> > +	"res_229",
> > +	"res_230",
> > +	"res_231",
> > +	"res_232",
> > +	"res_233",
> > +	"res_234",
> > +	"res_235",
> > +	"res_236",
> > +	"res_237",
> > +	"res_238",
> > +	"res_239",
> > +	"res_240",
> > +	"res_241",
> > +	"res_242",
> > +	"res_243",
> > +	"res_244",
> > +	"res_245",
> > +	"res_246",
> > +	"res_247",
> > +	"res_248",
> > +	"res_249",
> > +	"res_250",
> > +	"res_251",
> > +	"res_252",
> > +	"res_253",
> > +	"res_254",
> > +	"oem_unit",
> > +};
> > +
> >  static struct inode *stlmfs_get_inode(struct super_block *sb)
> >  {
> >  	struct inode *inode = new_inode(sb);
> > @@ -815,6 +1337,18 @@ DEFINE_TLM_CLASS(persistent_tlmo, "persistent", 0,
> >  DEFINE_TLM_CLASS(value_tlmo, "value", 0,
> >  		 S_IFREG | S_IRUSR, &de_read_fops, NULL);
> >  
> > +static inline struct dentry *
> > +stlmfs_lookup_by_name(struct dentry *parent, const char *dname)
> > +{
> > +	struct qstr qstr;
> > +
> > +	qstr.name = dname;
> > +	qstr.len = strlen(dname);
> > +	qstr.hash = full_name_hash(parent, qstr.name, qstr.len);
> > +
> > +	return d_lookup(parent, &qstr);
> > +}
> > +
> >  static int scmi_telemetry_de_populate(struct super_block *sb,
> >  				      struct scmi_tlm_setup *tsp,
> >  				      struct dentry *parent,
> > @@ -1659,6 +2193,150 @@ static struct dentry *stlmfs_create_root_dentry(struct super_block *sb)
> >  	return dentry;
> >  }
> >  
> > +static int scmi_telemetry_de_subdir_symlink(struct super_block *sb,
> > +					    struct scmi_tlm_setup *tsp,
> > +					    const struct scmi_telemetry_de *de,
> > +					    struct dentry *parent)
> > +{
> > +	struct dentry *dentry;
> > +	struct inode *inode;
> > +	int ret;
> I notice that ret isn't assigned a value and the function returns ret without
> initialising.
>

Yep, my bad: I think it is just a leftover from some last minute cleanup
I have done...it seems to cause only harmless (but noisy) error
messages...thanks for testing...I will fix !

> > +
> > +	if (IS_ERR(parent))
> >  

[snip]

> 
> I will continue reviewing,

Yes please, thanks for having a look.

Thanks,
Cristian