[PATCH v6 4/6] coresight: config: extract shared structures to common header file

From: Mike Leach
Date: Thu May 11 2023 - 02:53:51 EST


Extract shared user space and kernel common structures from
coresight-config.h into common header file coresight-config-desc.h

Abstract memory allocation in coresight-config-table.c to allow read
table functions to be run in userspace and kernel drivers.

Signed-off-by: Mike Leach <mike.leach@xxxxxxxxxx>
---
.../coresight/coresight-config-desc.h | 105 ++++++++++++++++
.../coresight/coresight-config-table.c | 66 +++++-----
.../hwtracing/coresight/coresight-config.h | 119 ++++--------------
3 files changed, 165 insertions(+), 125 deletions(-)
create mode 100644 drivers/hwtracing/coresight/coresight-config-desc.h

diff --git a/drivers/hwtracing/coresight/coresight-config-desc.h b/drivers/hwtracing/coresight/coresight-config-desc.h
new file mode 100644
index 000000000000..4a487743d7e2
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-config-desc.h
@@ -0,0 +1,105 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2020-2022 Linaro Limited, All rights reserved.
+ * Author: Mike Leach <mike.leach@xxxxxxxxxx>
+ */
+
+#ifndef _CORESIGHT_CORESIGHT_CONFIG_DESC_H
+#define _CORESIGHT_CORESIGHT_CONFIG_DESC_H
+
+/* Coresight Descriptors common to kernel and userspace applications */
+/*
+ * Register type flags for register value descriptor:
+ * describe how the value is interpreted, and handled.
+ */
+#define CS_CFG_REG_TYPE_STD 0x80 /* reg is standard reg */
+#define CS_CFG_REG_TYPE_RESOURCE 0x40 /* reg is a resource */
+#define CS_CFG_REG_TYPE_VAL_PARAM 0x08 /* reg value uses param */
+#define CS_CFG_REG_TYPE_VAL_MASK 0x04 /* reg value bit masked */
+#define CS_CFG_REG_TYPE_VAL_64BIT 0x02 /* reg value 64 bit */
+#define CS_CFG_REG_TYPE_VAL_SAVE 0x01 /* reg value save on disable */
+
+/*
+ * flags defining what device class a feature will match to when processing a
+ * system configuration - used by config data and devices.
+ */
+#define CS_CFG_MATCH_CLASS_SRC_ALL 0x0001 /* match any source */
+#define CS_CFG_MATCH_CLASS_SRC_ETM4 0x0002 /* match any ETMv4 device */
+
+/* flags defining device instance matching - used in config match desc data. */
+#define CS_CFG_MATCH_INST_ANY 0x80000000 /* any instance of a class */
+
+/*
+ * Limit number of presets in a configuration
+ * This is related to the number of bits (4) we use to select the preset on
+ * the perf command line. Preset 0 is always none selected.
+ * See PMU_FORMAT_ATTR(preset, "config:0-3") in coresight-etm-perf.c
+ */
+#define CS_CFG_CONFIG_PRESET_MAX 15
+
+/**
+ * Parameter descriptor for a device feature.
+ *
+ * @name: Name of parameter.
+ * @value: Initial or default value.
+ */
+struct cscfg_parameter_desc {
+ const char *name;
+ u64 value;
+};
+
+/**
+ * Representation of register value and a descriptor of register usage.
+ *
+ * Used as a descriptor in the feature descriptors.
+ * Used as a value in when in a feature loading into a csdev.
+ *
+ * Supports full 64 bit register value, or 32 bit value with optional mask
+ * value.
+ *
+ * @type: define register usage and interpretation.
+ * @offset: the address offset for register in the hardware device (per device specification).
+ * @hw_info: optional hardware device type specific information. (ETM / CTI specific etc)
+ * @val64: 64 bit value.
+ * @val32: 32 bit value.
+ * @mask32: 32 bit mask when using 32 bit value to access device register - if mask type.
+ * @param_idx: parameter index value into parameter array if param type.
+ */
+struct cscfg_regval_desc {
+ struct {
+ u32 type:8;
+ u32 offset:12;
+ u32 hw_info:12;
+ };
+ union {
+ u64 val64;
+ struct {
+ u32 val32;
+ u32 mask32;
+ };
+ u32 param_idx;
+ };
+};
+
+/**
+ * Dynamically loaded descriptor arrays.
+ *
+ * For builtin or module loaded configurations / features these are
+ * statically defined at compile time.
+
+ * For a dynamic load at runtime, using a config table, (e.g. load from
+ * configfs) we create the arrays dynamically so need a structure to
+ * manage these.
+ *
+ * @config_descs: array of config descriptor pointers.
+ * @feat_descs: array of feature descriptor pointers.
+ * @load_name: user readable name which may be used to unload later.
+ * Will be name of first config if present, or first feature.
+ */
+struct cscfg_table_load_descs {
+ struct cscfg_config_desc **config_descs;
+ struct cscfg_feature_desc **feat_descs;
+ char *load_name;
+};
+
+#endif /* _CORESIGHT_CORESIGHT_CONFIG_DESC_H */
diff --git a/drivers/hwtracing/coresight/coresight-config-table.c b/drivers/hwtracing/coresight/coresight-config-table.c
index 0a8f017d76d2..6216dffc9f9e 100644
--- a/drivers/hwtracing/coresight/coresight-config-table.c
+++ b/drivers/hwtracing/coresight/coresight-config-table.c
@@ -79,6 +79,7 @@ static int cscfg_table_read_elem_str(const u8 *buffer, const int buflen, int *bu
struct cscfg_table_elem_str *elem_str)
{
int used = *buf_used;
+ const u8 *str;

if ((buflen - used) < sizeof(u16))
return -EINVAL;
@@ -88,11 +89,13 @@ static int cscfg_table_read_elem_str(const u8 *buffer, const int buflen, int *bu
if ((buflen - used) < elem_str->str_len)
return -EINVAL;

+ str = buffer + used;
+
/* check for 0 termination */
- if (buffer[used + (elem_str->str_len - 1)] != 0)
+ if (str[elem_str->str_len - 1] != 0)
return -EINVAL;

- elem_str->str = kstrdup((char *)(buffer + used), GFP_KERNEL);
+ elem_str->str = cscfg_strdup((char *)str);
used += elem_str->str_len;

*buf_used = used;
@@ -103,12 +106,13 @@ static int cscfg_table_alloc_desc_arrays(struct cscfg_table_load_descs *desc_arr
int nr_features, int nr_configs)
{
/* arrays are 0 terminated - nr_configs & nr_features elements */
- desc_arrays->config_descs = kcalloc(nr_configs + 1, sizeof(struct cscfg_config_desc *),
- GFP_KERNEL);
+ desc_arrays->config_descs = cscfg_calloc(nr_configs + 1,
+ sizeof(struct cscfg_config_desc *));
if (!desc_arrays->config_descs)
return -ENOMEM;
- desc_arrays->feat_descs = kcalloc(nr_features + 1, sizeof(struct cscfg_feature_desc *),
- GFP_KERNEL);
+
+ desc_arrays->feat_descs = cscfg_calloc(nr_features + 1,
+ sizeof(struct cscfg_feature_desc *));
if (!desc_arrays->feat_descs)
return -ENOMEM;
return 0;
@@ -123,24 +127,24 @@ static void cscfg_table_free_config_desc(struct cscfg_config_desc *config_desc)
return;

/* free presets */
- kfree(config_desc->presets);
+ cscfg_free((void *)config_desc->presets);

/* free feat ref strings */
if (config_desc->nr_feat_refs) {
/* each string */
for (i = 0; i < config_desc->nr_feat_refs; i++)
- kfree(config_desc->feat_ref_names[i]);
+ cscfg_free((void *)config_desc->feat_ref_names[i]);

/* and the char * array */
- kfree(config_desc->feat_ref_names);
+ cscfg_free((void *)config_desc->feat_ref_names);
}

/* next the strings */
- kfree(config_desc->name);
- kfree(config_desc->description);
+ cscfg_free((void *)config_desc->name);
+ cscfg_free((void *)config_desc->description);

/* finally the struct itself */
- kfree(config_desc);
+ cscfg_free((void *)config_desc);
}

static int cscfg_table_read_elem_config(const u8 *buffer, const int buflen, int *buf_used,
@@ -165,7 +169,7 @@ static int cscfg_table_read_elem_config(const u8 *buffer, const int buflen, int
return 0;

/* we have a config - allocate the descriptor */
- config_desc = kzalloc(sizeof(struct cscfg_config_desc), GFP_KERNEL);
+ config_desc = cscfg_zalloc(sizeof(struct cscfg_config_desc));
if (!config_desc)
return -ENOMEM;

@@ -177,7 +181,7 @@ static int cscfg_table_read_elem_config(const u8 *buffer, const int buflen, int

/* allocate load name if not set */
if (!desc_arrays->load_name)
- desc_arrays->load_name = kstrdup(config_desc->name, GFP_KERNEL);
+ desc_arrays->load_name = cscfg_strdup(config_desc->name);

/* read the description string */
err = cscfg_table_read_elem_str(buffer, buflen, &used, &elem_str);
@@ -195,7 +199,7 @@ static int cscfg_table_read_elem_config(const u8 *buffer, const int buflen, int
/* read the array of 64bit presets if present */
nr_preset_vals = config_desc->nr_total_params * config_desc->nr_presets;
if (nr_preset_vals) {
- presets = kcalloc(nr_preset_vals, sizeof(u64), GFP_KERNEL);
+ presets = cscfg_calloc(nr_preset_vals, sizeof(u64));
if (!presets)
return -ENOMEM;

@@ -210,8 +214,8 @@ static int cscfg_table_read_elem_config(const u8 *buffer, const int buflen, int

/* read the array of feature names referenced by the config */
if (config_desc->nr_feat_refs) {
- config_desc->feat_ref_names = kcalloc(config_desc->nr_feat_refs,
- sizeof(char *), GFP_KERNEL);
+ config_desc->feat_ref_names = cscfg_calloc(config_desc->nr_feat_refs,
+ sizeof(char *));
if (!config_desc->feat_ref_names)
return -ENOMEM;

@@ -255,17 +259,17 @@ static void cscfg_table_free_feat_desc(struct cscfg_feature_desc *feat_desc)
return;

/* free up the register descriptor array */
- kfree(feat_desc->regs_desc);
+ cscfg_free((void *)feat_desc->regs_desc);

/* free up the parameters array */
- kfree(feat_desc->params_desc);
+ cscfg_free((void *)feat_desc->params_desc);

/* name and description strings */
- kfree(feat_desc->name);
- kfree(feat_desc->description);
+ cscfg_free((void *)feat_desc->name);
+ cscfg_free((void *)feat_desc->description);

/* finally the struct itself */
- kfree(feat_desc);
+ cscfg_free((void *)feat_desc);
}

static int cscfg_table_read_elem_feature(const u8 *buffer, const int buflen, int *buf_used,
@@ -280,7 +284,7 @@ static int cscfg_table_read_elem_feature(const u8 *buffer, const int buflen, int
u32 val32;

/* allocate the feature descriptor object */
- feat_desc = kzalloc(sizeof(struct cscfg_feature_desc), GFP_KERNEL);
+ feat_desc = cscfg_zalloc(sizeof(struct cscfg_feature_desc));
if (!feat_desc)
return -ENOMEM;

@@ -300,7 +304,7 @@ static int cscfg_table_read_elem_feature(const u8 *buffer, const int buflen, int

/* allocate load name if not set previously by config */
if (!desc_arrays->load_name)
- desc_arrays->load_name = kstrdup(feat_desc->name, GFP_KERNEL);
+ desc_arrays->load_name = cscfg_strdup(feat_desc->name);

/* read the description string */
err = cscfg_table_read_elem_str(buffer, buflen, &used, &elem_str);
@@ -323,8 +327,8 @@ static int cscfg_table_read_elem_feature(const u8 *buffer, const int buflen, int
nr_regs_bytes = ((sizeof(u32) + sizeof(u64)) * feat_desc->nr_regs);
if ((buflen - used) < nr_regs_bytes)
return -EINVAL;
- feat_desc->regs_desc = kcalloc(feat_desc->nr_regs,
- sizeof(struct cscfg_regval_desc), GFP_KERNEL);
+ feat_desc->regs_desc = cscfg_calloc(feat_desc->nr_regs,
+ sizeof(struct cscfg_regval_desc));
if (!feat_desc->regs_desc)
return -ENOMEM;

@@ -338,8 +342,8 @@ static int cscfg_table_read_elem_feature(const u8 *buffer, const int buflen, int

/* parameter descriptors - string + 64 bit value */
if (feat_desc->nr_params) {
- feat_desc->params_desc = kcalloc(feat_desc->nr_params,
- sizeof(struct cscfg_parameter_desc), GFP_KERNEL);
+ feat_desc->params_desc = cscfg_calloc(feat_desc->nr_params,
+ sizeof(struct cscfg_parameter_desc));
if (!feat_desc->params_desc)
return -ENOMEM;
for (i = 0; i < feat_desc->nr_params; i++) {
@@ -421,7 +425,7 @@ void cscfg_table_free_load_descs(struct cscfg_table_load_descs *desc_arrays)
}

/* finally free up the load descs pointer arrays */
- kfree(desc_arrays->config_descs);
- kfree(desc_arrays->feat_descs);
- kfree(desc_arrays->load_name);
+ cscfg_free(desc_arrays->config_descs);
+ cscfg_free(desc_arrays->feat_descs);
+ cscfg_free(desc_arrays->load_name);
}
diff --git a/drivers/hwtracing/coresight/coresight-config.h b/drivers/hwtracing/coresight/coresight-config.h
index ea3aaf0d129b..8b298e9a3776 100644
--- a/drivers/hwtracing/coresight/coresight-config.h
+++ b/drivers/hwtracing/coresight/coresight-config.h
@@ -10,101 +10,10 @@
#include <linux/coresight.h>
#include <linux/types.h>

-/* CoreSight Configuration Management - component and system wide configuration */
-
-/*
- * Register type flags for register value descriptor:
- * describe how the value is interpreted, and handled.
- */
-#define CS_CFG_REG_TYPE_STD 0x80 /* reg is standard reg */
-#define CS_CFG_REG_TYPE_RESOURCE 0x40 /* reg is a resource */
-#define CS_CFG_REG_TYPE_VAL_PARAM 0x08 /* reg value uses param */
-#define CS_CFG_REG_TYPE_VAL_MASK 0x04 /* reg value bit masked */
-#define CS_CFG_REG_TYPE_VAL_64BIT 0x02 /* reg value 64 bit */
-#define CS_CFG_REG_TYPE_VAL_SAVE 0x01 /* reg value save on disable */
-
-/*
- * flags defining what device class a feature will match to when processing a
- * system configuration - used by config data and devices.
- */
-#define CS_CFG_MATCH_CLASS_SRC_ALL 0x0001 /* match any source */
-#define CS_CFG_MATCH_CLASS_SRC_ETM4 0x0002 /* match any ETMv4 device */
-
-/* flags defining device instance matching - used in config match desc data. */
-#define CS_CFG_MATCH_INST_ANY 0x80000000 /* any instance of a class */
-
-/*
- * Limit number of presets in a configuration
- * This is related to the number of bits (4) we use to select the preset on
- * the perf command line. Preset 0 is always none selected.
- * See PMU_FORMAT_ATTR(preset, "config:0-3") in coresight-etm-perf.c
- */
-#define CS_CFG_CONFIG_PRESET_MAX 15
-
-/**
- * Parameter descriptor for a device feature.
- *
- * @name: Name of parameter.
- * @value: Initial or default value.
- */
-struct cscfg_parameter_desc {
- const char *name;
- u64 value;
-};
-
-/**
- * Representation of register value and a descriptor of register usage.
- *
- * Used as a descriptor in the feature descriptors.
- * Used as a value in when in a feature loading into a csdev.
- *
- * Supports full 64 bit register value, or 32 bit value with optional mask
- * value.
- *
- * @type: define register usage and interpretation.
- * @offset: the address offset for register in the hardware device (per device specification).
- * @hw_info: optional hardware device type specific information. (ETM / CTI specific etc)
- * @val64: 64 bit value.
- * @val32: 32 bit value.
- * @mask32: 32 bit mask when using 32 bit value to access device register - if mask type.
- * @param_idx: parameter index value into parameter array if param type.
- */
-struct cscfg_regval_desc {
- struct {
- u32 type:8;
- u32 offset:12;
- u32 hw_info:12;
- };
- union {
- u64 val64;
- struct {
- u32 val32;
- u32 mask32;
- };
- u32 param_idx;
- };
-};
-
-/**
- * Dynamically loaded descriptor arrays.
- *
- * For builtin or module loaded configurations / features these are
- * statically defined at compile time.
+/* common descriptor definitions */
+#include "coresight-config-desc.h"

- * For a dynamic load at runtime, using a config table, (e.g. load from
- * configfs) we create the arrays dynamically so need a structure to
- * manage these.
- *
- * @config_descs: array of config descriptor pointers.
- * @feat_descs: array of feature descriptor pointers.
- * @load_name: user readable name which may be used to unload later.
- * Will be name of first config if present, or first feature.
- */
-struct cscfg_table_load_descs {
- struct cscfg_config_desc **config_descs;
- struct cscfg_feature_desc **feat_descs;
- char *load_name;
-};
+/* CoreSight Configuration Management - component and system wide configuration */

/**
* Device feature descriptor - combination of registers and parameters to
@@ -280,4 +189,26 @@ void cscfg_csdev_disable_config(struct cscfg_config_csdev *config_csdev);
/* reset a feature to default values */
void cscfg_reset_feat(struct cscfg_feature_csdev *feat_csdev);

+
+/* Kernel allocators for descriptors in common config table read code */
+static inline void *cscfg_calloc(size_t num, size_t size)
+{
+ return kcalloc(num, size, GFP_KERNEL);
+}
+
+static inline char *cscfg_strdup(const char *str)
+{
+ return kstrdup(str, GFP_KERNEL);
+}
+
+static inline void *cscfg_zalloc(size_t size)
+{
+ return kzalloc(size, GFP_KERNEL);
+}
+
+static inline void cscfg_free(void *mem)
+{
+ kfree(mem);
+}
+
#endif /* _CORESIGHT_CORESIGHT_CONFIG_H */
--
2.17.1