Message ID | 20201030175655.30126-2-mike.leach@linaro.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | CoreSight complex config support; ETM strobing | expand |
Good day, I have started looking at this patchset yesterday - the documentation really helps. As usual comments will be staggered over several days. Some can be found below. On Fri, Oct 30, 2020 at 05:56:47PM +0000, Mike Leach wrote: > Creates an system management API to allow complex configurations and > features to be programmed into a CoreSight infrastructure. > > A feature is defined as a programming set for a device or class of > devices. > > A configuration is a set of features across the system that are enabled > for a trace session. > > The API will manage system wide configuration, and allow complex > programmed features to be added to individual device instances, and > provide for system wide configuration selection on trace capture > operations. > > This patch creates the initial data object and the initial API for > loading configurations and features. > > Signed-off-by: Mike Leach <mike.leach@linaro.org> > --- > drivers/hwtracing/coresight/Makefile | 2 +- > .../hwtracing/coresight/coresight-config.h | 170 ++++++++++++ > drivers/hwtracing/coresight/coresight-core.c | 12 +- > .../hwtracing/coresight/coresight-etm-perf.c | 2 +- > .../hwtracing/coresight/coresight-etm-perf.h | 2 +- > .../hwtracing/coresight/coresight-syscfg.c | 247 ++++++++++++++++++ > .../hwtracing/coresight/coresight-syscfg.h | 57 ++++ > 7 files changed, 488 insertions(+), 4 deletions(-) > create mode 100644 drivers/hwtracing/coresight/coresight-config.h > create mode 100644 drivers/hwtracing/coresight/coresight-syscfg.c > create mode 100644 drivers/hwtracing/coresight/coresight-syscfg.h > > diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile > index f20e357758d1..4ce854c434b1 100644 > --- a/drivers/hwtracing/coresight/Makefile > +++ b/drivers/hwtracing/coresight/Makefile > @@ -4,7 +4,7 @@ > # > obj-$(CONFIG_CORESIGHT) += coresight.o > coresight-y := coresight-core.o coresight-etm-perf.o coresight-platform.o \ > - coresight-sysfs.o > + coresight-sysfs.o coresight-syscfg.o > obj-$(CONFIG_CORESIGHT_LINK_AND_SINK_TMC) += coresight-tmc.o > coresight-tmc-y := coresight-tmc-core.o coresight-tmc-etf.o \ > coresight-tmc-etr.o > diff --git a/drivers/hwtracing/coresight/coresight-config.h b/drivers/hwtracing/coresight/coresight-config.h > new file mode 100644 > index 000000000000..0d9ae1dc4517 > --- /dev/null > +++ b/drivers/hwtracing/coresight/coresight-config.h > @@ -0,0 +1,170 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * Copyright (c) 2020 Linaro Limited, All rights reserved. > + * Author: Mike Leach <mike.leach@linaro.org> > + */ > + > +#ifndef _CORESIGHT_CORESIGHT_CONFIG_H > +#define _CORESIGHT_CORESIGHT_CONFIG_H > + > +#include <linux/coresight.h> > +#include <linux/types.h> > + > +/* CoreSight Configuration - complex component and system config handling */ > + > +/* generic register flags */ > +#define CS_CFG_REG_STD 0x80000000 /* reg is standard reg */ > +#define CS_CFG_REG_RESOURCE 0x40000000 /* reg is a resource */ > +#define CS_CFG_REG_VAL_PARAM 0x08000000 /* reg value uses param */ > +#define CS_CFG_REG_VAL_MASK 0x04000000 /* reg value bit masked */ > +#define CS_CFG_REG_VAL_64BIT 0x02000000 /* reg value 64 bit */ > +#define CS_CFG_REG_VAL_SAVE 0x01000000 /* reg value save on disable */ > +#define CS_CFG_REG_ID_MASK 0x00000FFF /* reg offset / id in device */ > +#define CS_CFG_REG_DEV_MASK 0x00FFF000 /* device specific flags */ > + > +/* > + * 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 */ > +#define CS_CFG_MATCH_CLASS_CTI_ALL 0x0004 /* match any CTI device */ > +#define CS_CFG_MATCH_CLASS_CTI_CPU 0x0008 > +#define CS_CFG_MATCH_CLASS_CTI_SYS 0x0010 > + > +/* flags defining device instance matching - used in config data. */ > +#define CS_CFG_MATCH_INST_ANY 0x80000000 /* any instance of a class */ > +#define CS_CFG_MATCH_INST_AMBA_DEVICE 0x40000000 /* specific amba device */ Is there a real need for the above two in this set? As far as I can tell the etmv4 and CTI flags would be enough. > + > +/* > + * 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 > + > + Extra line > +/** > + * 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. > + * > + * Supports full 64 bit register value, or 32 bit value with optional mask > + * value. > + * > + * @flags: define value usage as 32bit, 32bit+mask or 64bit. > + * @val64: 64 bit value. > + * @val32: 32 bit value. > + * @mask32: 32 bit mask when using 32 bit value to access device register. > + */ > +struct cscfg_regval { > + u32 flags; This field has to be unpacked, i.e u16 flags; u16 address; Otherwise it is impossible to understand what a cscfg_regval is. Moreover I'm worried about the "flags" and all the possible values. We have to think about how people will be using this thing and right now it is difficult. > + union { > + u64 val64; > + struct { > + u32 val32; > + u32 mask32; > + }; > + }; > +}; > + > + Extra line > +/** > + * Device feature descriptor - combination of registers and parameters to > + * program a device to implement a specific complex function. > + * > + * @name: feature name. > + * @brief: brief description of the feature. > + * @item: List entry. > + * @match_flags: matching information if loading into a device > + * @nr_params: number of parameters used. > + * @params: array of parameters used. > + * @nr_regs: number of registers used. > + * @reg: array of registers used. > + */ > +struct cscfg_feature_desc { > + const char *name; > + const char *brief; > + struct list_head item; > + u32 match_flags; > + int nr_params; > + struct cscfg_parameter_desc *params; > + int nr_regs; > + struct cscfg_regval *regs; > +}; > + > +/** > + * Device / feature matching information. > + * > + * Used by loading configurations to define which class or specific devices > + * they want to match used features to, and registered devices to specify which > + * matching class and information they support. > + * The load process uses these matching pairs to load feature instances into > + * matching devices. > + * > + * @match_flags: used to match to a particular class of device. > + * @dev_name: used to match to a particular device instance on the system. > + * > + */ > +struct cscfg_match_info { > + u32 match_flags; > + /* unique device name (e.g. amba bus name) for specific device match */ > + const char *dev_name; Again I'm not sure there is an immediate need for *dev_name in this set. Just having a match_flag in cscfg_config_feat_ref would be enough. > +}; > + > +/** > + * Descriptor for features referenced by a configuration. > + * > + * @name: name of feature to use. Match against the @name in struct > + * cscfg_feature_desc. > + * @nr_params: number of parameters the feature has. > + * @match: match info for the feature when used in this configuration - > + * may be all devices of a class or a specific device in that class. > + */ > +struct cscfg_config_feat_ref { > + const char *name; > + int nr_params; It is possible, using *name, to get to the cscfg_feature_desc where nr_params is defined. Looking at patch 06, having nr_params here is duplicating the information already available in cscfg_feature_desc - can it be removed completely? > + struct cscfg_match_info match; > +}; > + > +/** > + * Configuration descriptor - describes selectable system configuration. > + * > + * A configuration describes device features in use, and may provide preset > + * values for the parameters in those features. > + * > + * A single set of presets is the sum of the parameters declared by > + * all the features in use - this value is @nr_total_params. > + * > + * @name: name of the configuration - used for selection. > + * @brief: description of the purpose of the configuration. > + * @item: list entry. > + * @nr_refs: Number of features used in this configuration. > + * @refs: references to features used in this configuration.. > + * @nr_presets: Number of sets of presets supplied by this configuration. > + * @nr_total_params: Sum of all parameters declared by used features > + * @presets: Array of preset values. > + * Extra line > + */ > +struct cscfg_config_desc { > + const char *name; > + const char *brief; > + struct list_head item; > + int nr_refs; > + struct cscfg_config_feat_ref *refs; > + int nr_presets; > + int nr_total_params; > + const u64 *presets; /* nr_presets * nr_total_params */ In this patchset the presets are easy because autofdo has a single feature and there is only 2 parameters for this feature. I worry about what things will look like when a configuration has 6 featurse, each with a varying number of parameters. Here too I don't have a clear answer on how to proceed but it will need to be revised. > +}; Aligning the name of the structures in this file has really helped, thanks for doing that. More comments to come. Thanks, Mathieu > + > +#endif /* _CORESIGHT_CORESIGHT_CONFIG_H */ > diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c > index 29c83eac3106..481d2b7b6b6f 100644 > --- a/drivers/hwtracing/coresight/coresight-core.c > +++ b/drivers/hwtracing/coresight/coresight-core.c > @@ -21,6 +21,7 @@ > > #include "coresight-etm-perf.h" > #include "coresight-priv.h" > +#include "coresight-syscfg.h" > > static DEFINE_MUTEX(coresight_mutex); > > @@ -1675,13 +1676,22 @@ static int __init coresight_init(void) > > ret = etm_perf_init(); > if (ret) > - bus_unregister(&coresight_bustype); > + goto exit_bus_unregister; > > + /* initialise the coresight syscfg API */ > + ret = cscfg_init(); > + if (!ret) > + return 0; > + > + etm_perf_exit(); > +exit_bus_unregister: > + bus_unregister(&coresight_bustype); > return ret; > } > > static void __exit coresight_exit(void) > { > + cscfg_exit(); > etm_perf_exit(); > bus_unregister(&coresight_bustype); > } > diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c > index bdc34ca449f7..a608081bd446 100644 > --- a/drivers/hwtracing/coresight/coresight-etm-perf.c > +++ b/drivers/hwtracing/coresight/coresight-etm-perf.c > @@ -627,7 +627,7 @@ int __init etm_perf_init(void) > return ret; > } > > -void __exit etm_perf_exit(void) > +void etm_perf_exit(void) > { > perf_pmu_unregister(&etm_pmu); > } > diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.h b/drivers/hwtracing/coresight/coresight-etm-perf.h > index 3e4f2ad5e193..29d90dfeba31 100644 > --- a/drivers/hwtracing/coresight/coresight-etm-perf.h > +++ b/drivers/hwtracing/coresight/coresight-etm-perf.h > @@ -83,6 +83,6 @@ static inline void *etm_perf_sink_config(struct perf_output_handle *handle) > #endif /* CONFIG_CORESIGHT */ > > int __init etm_perf_init(void); > -void __exit etm_perf_exit(void); > +void etm_perf_exit(void); > > #endif > diff --git a/drivers/hwtracing/coresight/coresight-syscfg.c b/drivers/hwtracing/coresight/coresight-syscfg.c > new file mode 100644 > index 000000000000..6f89541af7a0 > --- /dev/null > +++ b/drivers/hwtracing/coresight/coresight-syscfg.c > @@ -0,0 +1,247 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright (c) 2020 Linaro Limited, All rights reserved. > + * Author: Mike Leach <mike.leach@linaro.org> > + */ > + > +#include <linux/platform_device.h> > + > +#include "coresight-config.h" > +#include "coresight-syscfg.h" > + > +/* > + * cscfg_ API manages configurations and features for the entire coresight > + * infrastructure. > + * > + * It allows the loading of configurations and features, and loads these into > + * coresight devices as appropriate. > + */ > + > +static DEFINE_MUTEX(cscfg_mutex); > + > +/* only one of these */ > +static struct cscfg_api_data cscfg_data; > + > +/* get reference to cscfg device */ > +struct device *to_device_cscfg(void); > + > +/* load features and configuations into the lists */ > + > +/* check feature list for a named feature - call with mutex locked. */ > +static bool cscfg_match_list_feat(const char *name) > +{ > + struct cscfg_feature_desc *curr_item; > + > + list_for_each_entry(curr_item, &cscfg_data.feat_list, item) { > + if (strcmp(curr_item->name, name) == 0) > + return true; > + } > + return false; > +} > + > +/* check all feat needed for cfg are in the list - call with mutex locked. */ > +static int cscfg_check_feat_for_cfg(struct cscfg_config_desc *cfg_desc) > +{ > + int i; > + > + for (i = 0; i < cfg_desc->nr_refs; i++) > + if (!cscfg_match_list_feat(cfg_desc->refs[i].name)) > + return -EINVAL; > + return 0; > +} > + > +/* > + * load feature - add to feature list. > + */ > +static int cscfg_load_feat(struct cscfg_feature_desc *feat_desc) > +{ > + list_add(&feat_desc->item, &cscfg_data.feat_list); > + > + return 0; > +} > + > +/* > + * load config into the system - validate used features exist then add to > + * config list. > + */ > +static int cscfg_load_config(struct cscfg_config_desc *cfg_desc) > +{ > + int err; > + > + /* validate features are present */ > + err = cscfg_check_feat_for_cfg(cfg_desc); > + if (err) > + return err; > + > + list_add(&cfg_desc->item, &cscfg_data.config_list); > + > + return 0; > +} > + > +/* > + * External API function to load feature and config sets. > + * Take a 0 terminated array of feature descriptors and/or configuration > + * descriptors and load into the system. > + * Features are loaded first to ensure configuration dependencies can be met. > + */ > +int cscfg_load_config_sets(struct cscfg_config_desc **cfg_descs, > + struct cscfg_feature_desc **feat_descs) > +{ > + int err, i = 0; > + > + mutex_lock(&cscfg_mutex); > + > + /* load features first */ > + if (feat_descs) { > + while (feat_descs[i]) { > + err = cscfg_load_feat(feat_descs[i]); > + if (err) { > + pr_err("coresight-syscfg: Failed to load feature %s\n", > + feat_descs[i]->name); > + goto do_unlock; > + } > + i++; > + } > + } > + > + /* next any configurations to check feature dependencies */ > + i = 0; > + if (cfg_descs) { > + while (cfg_descs[i]) { > + err = cscfg_load_config(cfg_descs[i]); > + if (err) { > + pr_err("coresight-syscfg: Failed to load configuration %s\n", > + cfg_descs[i]->name); > + goto do_unlock; > + } > + i++; > + } > + } > + > +do_unlock: > + mutex_unlock(&cscfg_mutex); > + return err; > +} > +EXPORT_SYMBOL_GPL(cscfg_load_config_sets); > + > +/* Initialise system configuration management driver. */ > +/* only one of these */ > +static struct cscfg_device *cscfg_dev; > + > +/* > + * We have a separate coresight-config bus for the config device so it does > + * not appear on the main coresight bus and affect device searches on that bus. > + */ > +static struct bus_type cscfg_bus_type = { > + .name = "coresight-config", > +}; > + > +struct device *to_device_cscfg(void) > +{ > + return cscfg_dev ? &cscfg_dev->dev : NULL; > +} > + > +/* Must have a release function or the kernel will complain on module unload */ > +void cscfg_dev_release(struct device *dev) > +{ > + kfree(cscfg_dev); > + cscfg_dev = NULL; > +} > + > +int cscfg_create_device(void) > +{ > + struct device *dev; > + int err = -ENOMEM; > + > + mutex_lock(&cscfg_mutex); > + if (cscfg_dev) { > + err = -EINVAL; > + goto create_dev_exit_unlock; > + } > + > + cscfg_dev = kzalloc(sizeof(struct cscfg_device), GFP_KERNEL); > + if (!cscfg_dev) > + goto create_dev_exit_unlock; > + > + /* setup the device */ > + dev = to_device_cscfg(); > + dev->bus = &cscfg_bus_type; > + dev->parent = &platform_bus; > + dev->release = cscfg_dev_release; > + dev->init_name = "system_cfg"; > + cscfg_dev->cfg_data = &cscfg_data; > + > + err = device_register(dev); > + if (err) > + cscfg_dev_release(dev); > + > +create_dev_exit_unlock: > + mutex_unlock(&cscfg_mutex); > + return err; > +} > + > +void cscfg_clear_device(void) > +{ > + mutex_lock(&cscfg_mutex); > + device_unregister(to_device_cscfg()); > + mutex_unlock(&cscfg_mutex); > +} > + > +/* driver initialisation */ > +static struct cscfg_driver cs_config_driver = { > + .drv = { > + .name = "cs-syscfg-drv", > + .owner = THIS_MODULE, > + .suppress_bind_attrs = true, > + }, > +}; > + > +int __init cscfg_driver_init(void) > +{ > + cs_config_driver.drv.bus = &cscfg_bus_type; > + return driver_register(&cs_config_driver.drv); > +} > + > +void cscfg_driver_exit(void) > +{ > + driver_unregister(&cs_config_driver.drv); > +} > + > +/* Initialise system config management API */ > +int __init cscfg_init(void) > +{ > + int err = 0; > + > + err = bus_register(&cscfg_bus_type); > + if (err) > + return err; > + > + err = cscfg_driver_init(); > + if (err) > + goto exit_bus_unregister; > + > + err = cscfg_create_device(); > + if (err) > + goto exit_drv_unregister; > + > + INIT_LIST_HEAD(&cscfg_data.dev_list); > + INIT_LIST_HEAD(&cscfg_data.feat_list); > + INIT_LIST_HEAD(&cscfg_data.config_list); > + cscfg_data.nr_csdev = 0; > + > + dev_info(to_device_cscfg(), "CoreSight Configuration manager initialised"); > + return 0; > + > +exit_drv_unregister: > + cscfg_driver_exit(); > +exit_bus_unregister: > + bus_unregister(&cscfg_bus_type); > + return err; > +} > + > +void __exit cscfg_exit(void) > +{ > + cscfg_clear_device(); > + cscfg_driver_exit(); > + bus_unregister(&cscfg_bus_type); > +} > diff --git a/drivers/hwtracing/coresight/coresight-syscfg.h b/drivers/hwtracing/coresight/coresight-syscfg.h > new file mode 100644 > index 000000000000..5a7896426eab > --- /dev/null > +++ b/drivers/hwtracing/coresight/coresight-syscfg.h > @@ -0,0 +1,57 @@ > +/* SPDX-License-Identifier: GPL-2.0-only */ > +/* > + * Coresight system configuration driver. > + */ > + > +#ifndef CORESIGHT_SYSCFG_H > +#define CORESIGHT_SYSCFG_H > + > +#include <linux/coresight.h> > +#include <linux/device.h> > + > +#include "coresight-config.h" > + > +/** > + * System configuration API data. > + * > + * @dev_list: List of other coresight devices registered with this device. > + * @feat_list: List of features to load into registered devices. > + * @config_list:List of system configurations to load into registered devices. > + * @nr_csdev: Number of registered devices with the cscfg system > + */ > +struct cscfg_api_data { > + struct list_head dev_list; > + struct list_head feat_list; > + struct list_head config_list; > + int nr_csdev; > +}; > + > +/* internal core operations for cscfg */ > +int __init cscfg_init(void); > +void __exit cscfg_exit(void); > + > +/* syscfg external API */ > +int cscfg_load_config_sets(struct cscfg_config_desc **cfg_descs, > + struct cscfg_feature_desc **feat_descs); > + > +/* system configuration device driver and API */ > +/** > + * System configuration device. > + * > + * Need a device to 'own' some coresight system wide sysfs entries in > + * perf events etc. > + * > + * @dev: The device. > + * @cfg_data: A reference to the configuration and feature lists > + */ > +struct cscfg_device { > + struct device dev; > + struct cscfg_api_data *cfg_data; > +}; > + > +/* basic device driver */ > +struct cscfg_driver { > + struct device_driver drv; > +}; > + > +#endif /* CORESIGHT_SYSCFG_H */ > -- > 2.17.1 >
On Fri, Oct 30, 2020 at 05:56:47PM +0000, Mike Leach wrote: > Creates an system management API to allow complex configurations and > features to be programmed into a CoreSight infrastructure. > > A feature is defined as a programming set for a device or class of > devices. > > A configuration is a set of features across the system that are enabled > for a trace session. > > The API will manage system wide configuration, and allow complex > programmed features to be added to individual device instances, and > provide for system wide configuration selection on trace capture > operations. > > This patch creates the initial data object and the initial API for > loading configurations and features. > > Signed-off-by: Mike Leach <mike.leach@linaro.org> > --- > drivers/hwtracing/coresight/Makefile | 2 +- > .../hwtracing/coresight/coresight-config.h | 170 ++++++++++++ > drivers/hwtracing/coresight/coresight-core.c | 12 +- > .../hwtracing/coresight/coresight-etm-perf.c | 2 +- > .../hwtracing/coresight/coresight-etm-perf.h | 2 +- > .../hwtracing/coresight/coresight-syscfg.c | 247 ++++++++++++++++++ > .../hwtracing/coresight/coresight-syscfg.h | 57 ++++ > 7 files changed, 488 insertions(+), 4 deletions(-) > create mode 100644 drivers/hwtracing/coresight/coresight-config.h > create mode 100644 drivers/hwtracing/coresight/coresight-syscfg.c > create mode 100644 drivers/hwtracing/coresight/coresight-syscfg.h > > diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile > index f20e357758d1..4ce854c434b1 100644 > --- a/drivers/hwtracing/coresight/Makefile > +++ b/drivers/hwtracing/coresight/Makefile > @@ -4,7 +4,7 @@ > # > obj-$(CONFIG_CORESIGHT) += coresight.o > coresight-y := coresight-core.o coresight-etm-perf.o coresight-platform.o \ > - coresight-sysfs.o > + coresight-sysfs.o coresight-syscfg.o > obj-$(CONFIG_CORESIGHT_LINK_AND_SINK_TMC) += coresight-tmc.o > coresight-tmc-y := coresight-tmc-core.o coresight-tmc-etf.o \ > coresight-tmc-etr.o > diff --git a/drivers/hwtracing/coresight/coresight-config.h b/drivers/hwtracing/coresight/coresight-config.h > new file mode 100644 > index 000000000000..0d9ae1dc4517 > --- /dev/null > +++ b/drivers/hwtracing/coresight/coresight-config.h > @@ -0,0 +1,170 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * Copyright (c) 2020 Linaro Limited, All rights reserved. > + * Author: Mike Leach <mike.leach@linaro.org> > + */ > + > +#ifndef _CORESIGHT_CORESIGHT_CONFIG_H > +#define _CORESIGHT_CORESIGHT_CONFIG_H > + > +#include <linux/coresight.h> > +#include <linux/types.h> > + > +/* CoreSight Configuration - complex component and system config handling */ > + > +/* generic register flags */ > +#define CS_CFG_REG_STD 0x80000000 /* reg is standard reg */ > +#define CS_CFG_REG_RESOURCE 0x40000000 /* reg is a resource */ > +#define CS_CFG_REG_VAL_PARAM 0x08000000 /* reg value uses param */ > +#define CS_CFG_REG_VAL_MASK 0x04000000 /* reg value bit masked */ > +#define CS_CFG_REG_VAL_64BIT 0x02000000 /* reg value 64 bit */ > +#define CS_CFG_REG_VAL_SAVE 0x01000000 /* reg value save on disable */ > +#define CS_CFG_REG_ID_MASK 0x00000FFF /* reg offset / id in device */ > +#define CS_CFG_REG_DEV_MASK 0x00FFF000 /* device specific flags */ > + > +/* > + * 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 */ > +#define CS_CFG_MATCH_CLASS_CTI_ALL 0x0004 /* match any CTI device */ > +#define CS_CFG_MATCH_CLASS_CTI_CPU 0x0008 > +#define CS_CFG_MATCH_CLASS_CTI_SYS 0x0010 > + > +/* flags defining device instance matching - used in config data. */ > +#define CS_CFG_MATCH_INST_ANY 0x80000000 /* any instance of a class */ > +#define CS_CFG_MATCH_INST_AMBA_DEVICE 0x40000000 /* specific amba device */ > + > +/* > + * 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. > + * > + * Supports full 64 bit register value, or 32 bit value with optional mask > + * value. > + * > + * @flags: define value usage as 32bit, 32bit+mask or 64bit. > + * @val64: 64 bit value. > + * @val32: 32 bit value. > + * @mask32: 32 bit mask when using 32 bit value to access device register. > + */ > +struct cscfg_regval { > + u32 flags; > + union { > + u64 val64; > + struct { > + u32 val32; > + u32 mask32; > + }; > + }; > +}; > + > + > +/** > + * Device feature descriptor - combination of registers and parameters to > + * program a device to implement a specific complex function. > + * > + * @name: feature name. > + * @brief: brief description of the feature. > + * @item: List entry. > + * @match_flags: matching information if loading into a device > + * @nr_params: number of parameters used. > + * @params: array of parameters used. > + * @nr_regs: number of registers used. > + * @reg: array of registers used. > + */ > +struct cscfg_feature_desc { > + const char *name; > + const char *brief; > + struct list_head item; > + u32 match_flags; > + int nr_params; > + struct cscfg_parameter_desc *params; > + int nr_regs; > + struct cscfg_regval *regs; > +}; > + > +/** > + * Device / feature matching information. > + * > + * Used by loading configurations to define which class or specific devices > + * they want to match used features to, and registered devices to specify which > + * matching class and information they support. > + * The load process uses these matching pairs to load feature instances into > + * matching devices. > + * > + * @match_flags: used to match to a particular class of device. > + * @dev_name: used to match to a particular device instance on the system. > + * > + */ > +struct cscfg_match_info { > + u32 match_flags; > + /* unique device name (e.g. amba bus name) for specific device match */ > + const char *dev_name; > +}; > + > +/** > + * Descriptor for features referenced by a configuration. > + * > + * @name: name of feature to use. Match against the @name in struct > + * cscfg_feature_desc. > + * @nr_params: number of parameters the feature has. > + * @match: match info for the feature when used in this configuration - > + * may be all devices of a class or a specific device in that class. > + */ > +struct cscfg_config_feat_ref { > + const char *name; > + int nr_params; > + struct cscfg_match_info match; > +}; > + > +/** > + * Configuration descriptor - describes selectable system configuration. > + * > + * A configuration describes device features in use, and may provide preset > + * values for the parameters in those features. > + * > + * A single set of presets is the sum of the parameters declared by > + * all the features in use - this value is @nr_total_params. > + * > + * @name: name of the configuration - used for selection. > + * @brief: description of the purpose of the configuration. > + * @item: list entry. > + * @nr_refs: Number of features used in this configuration. > + * @refs: references to features used in this configuration.. > + * @nr_presets: Number of sets of presets supplied by this configuration. > + * @nr_total_params: Sum of all parameters declared by used features > + * @presets: Array of preset values. > + * > + */ > +struct cscfg_config_desc { > + const char *name; > + const char *brief; > + struct list_head item; > + int nr_refs; > + struct cscfg_config_feat_ref *refs; > + int nr_presets; > + int nr_total_params; > + const u64 *presets; /* nr_presets * nr_total_params */ > +}; > + > +#endif /* _CORESIGHT_CORESIGHT_CONFIG_H */ > diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c > index 29c83eac3106..481d2b7b6b6f 100644 > --- a/drivers/hwtracing/coresight/coresight-core.c > +++ b/drivers/hwtracing/coresight/coresight-core.c > @@ -21,6 +21,7 @@ > > #include "coresight-etm-perf.h" > #include "coresight-priv.h" > +#include "coresight-syscfg.h" > > static DEFINE_MUTEX(coresight_mutex); > > @@ -1675,13 +1676,22 @@ static int __init coresight_init(void) > > ret = etm_perf_init(); > if (ret) > - bus_unregister(&coresight_bustype); > + goto exit_bus_unregister; > > + /* initialise the coresight syscfg API */ > + ret = cscfg_init(); > + if (!ret) > + return 0; > + > + etm_perf_exit(); > +exit_bus_unregister: > + bus_unregister(&coresight_bustype); > return ret; > } > > static void __exit coresight_exit(void) > { > + cscfg_exit(); > etm_perf_exit(); > bus_unregister(&coresight_bustype); > } > diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c > index bdc34ca449f7..a608081bd446 100644 > --- a/drivers/hwtracing/coresight/coresight-etm-perf.c > +++ b/drivers/hwtracing/coresight/coresight-etm-perf.c > @@ -627,7 +627,7 @@ int __init etm_perf_init(void) > return ret; > } > > -void __exit etm_perf_exit(void) > +void etm_perf_exit(void) > { > perf_pmu_unregister(&etm_pmu); > } > diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.h b/drivers/hwtracing/coresight/coresight-etm-perf.h > index 3e4f2ad5e193..29d90dfeba31 100644 > --- a/drivers/hwtracing/coresight/coresight-etm-perf.h > +++ b/drivers/hwtracing/coresight/coresight-etm-perf.h > @@ -83,6 +83,6 @@ static inline void *etm_perf_sink_config(struct perf_output_handle *handle) > #endif /* CONFIG_CORESIGHT */ > > int __init etm_perf_init(void); > -void __exit etm_perf_exit(void); > +void etm_perf_exit(void); > > #endif > diff --git a/drivers/hwtracing/coresight/coresight-syscfg.c b/drivers/hwtracing/coresight/coresight-syscfg.c > new file mode 100644 > index 000000000000..6f89541af7a0 > --- /dev/null > +++ b/drivers/hwtracing/coresight/coresight-syscfg.c > @@ -0,0 +1,247 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright (c) 2020 Linaro Limited, All rights reserved. > + * Author: Mike Leach <mike.leach@linaro.org> > + */ > + > +#include <linux/platform_device.h> > + > +#include "coresight-config.h" > +#include "coresight-syscfg.h" > + > +/* > + * cscfg_ API manages configurations and features for the entire coresight > + * infrastructure. > + * > + * It allows the loading of configurations and features, and loads these into > + * coresight devices as appropriate. > + */ > + > +static DEFINE_MUTEX(cscfg_mutex); > + > +/* only one of these */ > +static struct cscfg_api_data cscfg_data; > + > +/* get reference to cscfg device */ > +struct device *to_device_cscfg(void); > + > +/* load features and configuations into the lists */ > + > +/* check feature list for a named feature - call with mutex locked. */ > +static bool cscfg_match_list_feat(const char *name) > +{ > + struct cscfg_feature_desc *curr_item; > + > + list_for_each_entry(curr_item, &cscfg_data.feat_list, item) { > + if (strcmp(curr_item->name, name) == 0) > + return true; > + } > + return false; > +} > + > +/* check all feat needed for cfg are in the list - call with mutex locked. */ > +static int cscfg_check_feat_for_cfg(struct cscfg_config_desc *cfg_desc) > +{ > + int i; > + > + for (i = 0; i < cfg_desc->nr_refs; i++) > + if (!cscfg_match_list_feat(cfg_desc->refs[i].name)) > + return -EINVAL; > + return 0; > +} > + > +/* > + * load feature - add to feature list. > + */ > +static int cscfg_load_feat(struct cscfg_feature_desc *feat_desc) > +{ > + list_add(&feat_desc->item, &cscfg_data.feat_list); > + > + return 0; > +} > + > +/* > + * load config into the system - validate used features exist then add to > + * config list. > + */ > +static int cscfg_load_config(struct cscfg_config_desc *cfg_desc) > +{ > + int err; > + > + /* validate features are present */ > + err = cscfg_check_feat_for_cfg(cfg_desc); > + if (err) > + return err; > + > + list_add(&cfg_desc->item, &cscfg_data.config_list); > + > + return 0; > +} > + > +/* > + * External API function to load feature and config sets. > + * Take a 0 terminated array of feature descriptors and/or configuration > + * descriptors and load into the system. > + * Features are loaded first to ensure configuration dependencies can be met. > + */ > +int cscfg_load_config_sets(struct cscfg_config_desc **cfg_descs, > + struct cscfg_feature_desc **feat_descs) > +{ > + int err, i = 0; > + > + mutex_lock(&cscfg_mutex); > + > + /* load features first */ > + if (feat_descs) { > + while (feat_descs[i]) { > + err = cscfg_load_feat(feat_descs[i]); > + if (err) { > + pr_err("coresight-syscfg: Failed to load feature %s\n", > + feat_descs[i]->name); > + goto do_unlock; > + } > + i++; > + } > + } > + > + /* next any configurations to check feature dependencies */ > + i = 0; > + if (cfg_descs) { > + while (cfg_descs[i]) { > + err = cscfg_load_config(cfg_descs[i]); > + if (err) { > + pr_err("coresight-syscfg: Failed to load configuration %s\n", > + cfg_descs[i]->name); > + goto do_unlock; > + } > + i++; > + } > + } > + > +do_unlock: > + mutex_unlock(&cscfg_mutex); > + return err; > +} > +EXPORT_SYMBOL_GPL(cscfg_load_config_sets); For file coresight-syscfg.c I am good with the top to here. I will comment further on what comes below at a later time. > + > +/* Initialise system configuration management driver. */ > +/* only one of these */ > +static struct cscfg_device *cscfg_dev; > + > +/* > + * We have a separate coresight-config bus for the config device so it does > + * not appear on the main coresight bus and affect device searches on that bus. > + */ > +static struct bus_type cscfg_bus_type = { > + .name = "coresight-config", > +}; > + > +struct device *to_device_cscfg(void) > +{ > + return cscfg_dev ? &cscfg_dev->dev : NULL; > +} > + > +/* Must have a release function or the kernel will complain on module unload */ > +void cscfg_dev_release(struct device *dev) > +{ > + kfree(cscfg_dev); > + cscfg_dev = NULL; > +} > + > +int cscfg_create_device(void) > +{ > + struct device *dev; > + int err = -ENOMEM; > + > + mutex_lock(&cscfg_mutex); > + if (cscfg_dev) { > + err = -EINVAL; > + goto create_dev_exit_unlock; > + } > + > + cscfg_dev = kzalloc(sizeof(struct cscfg_device), GFP_KERNEL); > + if (!cscfg_dev) > + goto create_dev_exit_unlock; > + > + /* setup the device */ > + dev = to_device_cscfg(); > + dev->bus = &cscfg_bus_type; > + dev->parent = &platform_bus; > + dev->release = cscfg_dev_release; > + dev->init_name = "system_cfg"; > + cscfg_dev->cfg_data = &cscfg_data; > + > + err = device_register(dev); > + if (err) > + cscfg_dev_release(dev); > + > +create_dev_exit_unlock: > + mutex_unlock(&cscfg_mutex); > + return err; > +} > + > +void cscfg_clear_device(void) > +{ > + mutex_lock(&cscfg_mutex); > + device_unregister(to_device_cscfg()); > + mutex_unlock(&cscfg_mutex); > +} > + > +/* driver initialisation */ > +static struct cscfg_driver cs_config_driver = { > + .drv = { > + .name = "cs-syscfg-drv", > + .owner = THIS_MODULE, > + .suppress_bind_attrs = true, > + }, > +}; > + > +int __init cscfg_driver_init(void) > +{ > + cs_config_driver.drv.bus = &cscfg_bus_type; > + return driver_register(&cs_config_driver.drv); > +} > + > +void cscfg_driver_exit(void) > +{ > + driver_unregister(&cs_config_driver.drv); > +} > + > +/* Initialise system config management API */ > +int __init cscfg_init(void) > +{ > + int err = 0; > + > + err = bus_register(&cscfg_bus_type); > + if (err) > + return err; > + > + err = cscfg_driver_init(); > + if (err) > + goto exit_bus_unregister; > + > + err = cscfg_create_device(); > + if (err) > + goto exit_drv_unregister; > + > + INIT_LIST_HEAD(&cscfg_data.dev_list); > + INIT_LIST_HEAD(&cscfg_data.feat_list); > + INIT_LIST_HEAD(&cscfg_data.config_list); > + cscfg_data.nr_csdev = 0; > + > + dev_info(to_device_cscfg(), "CoreSight Configuration manager initialised"); > + return 0; > + > +exit_drv_unregister: > + cscfg_driver_exit(); > +exit_bus_unregister: > + bus_unregister(&cscfg_bus_type); > + return err; > +} > + > +void __exit cscfg_exit(void) > +{ > + cscfg_clear_device(); > + cscfg_driver_exit(); > + bus_unregister(&cscfg_bus_type); > +} > diff --git a/drivers/hwtracing/coresight/coresight-syscfg.h b/drivers/hwtracing/coresight/coresight-syscfg.h > new file mode 100644 > index 000000000000..5a7896426eab > --- /dev/null > +++ b/drivers/hwtracing/coresight/coresight-syscfg.h > @@ -0,0 +1,57 @@ > +/* SPDX-License-Identifier: GPL-2.0-only */ > +/* > + * Coresight system configuration driver. > + */ > + > +#ifndef CORESIGHT_SYSCFG_H > +#define CORESIGHT_SYSCFG_H > + > +#include <linux/coresight.h> > +#include <linux/device.h> > + > +#include "coresight-config.h" > + > +/** > + * System configuration API data. > + * > + * @dev_list: List of other coresight devices registered with this device. > + * @feat_list: List of features to load into registered devices. > + * @config_list:List of system configurations to load into registered devices. > + * @nr_csdev: Number of registered devices with the cscfg system > + */ > +struct cscfg_api_data { > + struct list_head dev_list; > + struct list_head feat_list; > + struct list_head config_list; > + int nr_csdev; > +}; > + > +/* internal core operations for cscfg */ > +int __init cscfg_init(void); > +void __exit cscfg_exit(void); > + > +/* syscfg external API */ > +int cscfg_load_config_sets(struct cscfg_config_desc **cfg_descs, > + struct cscfg_feature_desc **feat_descs); > + > +/* system configuration device driver and API */ > +/** > + * System configuration device. > + * > + * Need a device to 'own' some coresight system wide sysfs entries in > + * perf events etc. > + * > + * @dev: The device. > + * @cfg_data: A reference to the configuration and feature lists > + */ > +struct cscfg_device { > + struct device dev; > + struct cscfg_api_data *cfg_data; > +}; > + > +/* basic device driver */ > +struct cscfg_driver { > + struct device_driver drv; > +}; > + > +#endif /* CORESIGHT_SYSCFG_H */ > -- > 2.17.1 >
On Fri, Oct 30, 2020 at 05:56:47PM +0000, Mike Leach wrote: > Creates an system management API to allow complex configurations and > features to be programmed into a CoreSight infrastructure. > > A feature is defined as a programming set for a device or class of > devices. > > A configuration is a set of features across the system that are enabled > for a trace session. > > The API will manage system wide configuration, and allow complex > programmed features to be added to individual device instances, and > provide for system wide configuration selection on trace capture > operations. > > This patch creates the initial data object and the initial API for > loading configurations and features. > > Signed-off-by: Mike Leach <mike.leach@linaro.org> > --- > drivers/hwtracing/coresight/Makefile | 2 +- > .../hwtracing/coresight/coresight-config.h | 170 ++++++++++++ > drivers/hwtracing/coresight/coresight-core.c | 12 +- > .../hwtracing/coresight/coresight-etm-perf.c | 2 +- > .../hwtracing/coresight/coresight-etm-perf.h | 2 +- > .../hwtracing/coresight/coresight-syscfg.c | 247 ++++++++++++++++++ > .../hwtracing/coresight/coresight-syscfg.h | 57 ++++ > 7 files changed, 488 insertions(+), 4 deletions(-) > create mode 100644 drivers/hwtracing/coresight/coresight-config.h > create mode 100644 drivers/hwtracing/coresight/coresight-syscfg.c > create mode 100644 drivers/hwtracing/coresight/coresight-syscfg.h > > diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile > index f20e357758d1..4ce854c434b1 100644 > --- a/drivers/hwtracing/coresight/Makefile > +++ b/drivers/hwtracing/coresight/Makefile > @@ -4,7 +4,7 @@ > # > obj-$(CONFIG_CORESIGHT) += coresight.o > coresight-y := coresight-core.o coresight-etm-perf.o coresight-platform.o \ > - coresight-sysfs.o > + coresight-sysfs.o coresight-syscfg.o > obj-$(CONFIG_CORESIGHT_LINK_AND_SINK_TMC) += coresight-tmc.o > coresight-tmc-y := coresight-tmc-core.o coresight-tmc-etf.o \ > coresight-tmc-etr.o > diff --git a/drivers/hwtracing/coresight/coresight-config.h b/drivers/hwtracing/coresight/coresight-config.h > new file mode 100644 > index 000000000000..0d9ae1dc4517 > --- /dev/null > +++ b/drivers/hwtracing/coresight/coresight-config.h > @@ -0,0 +1,170 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * Copyright (c) 2020 Linaro Limited, All rights reserved. > + * Author: Mike Leach <mike.leach@linaro.org> > + */ > + > +#ifndef _CORESIGHT_CORESIGHT_CONFIG_H > +#define _CORESIGHT_CORESIGHT_CONFIG_H > + > +#include <linux/coresight.h> > +#include <linux/types.h> > + > +/* CoreSight Configuration - complex component and system config handling */ > + > +/* generic register flags */ > +#define CS_CFG_REG_STD 0x80000000 /* reg is standard reg */ > +#define CS_CFG_REG_RESOURCE 0x40000000 /* reg is a resource */ > +#define CS_CFG_REG_VAL_PARAM 0x08000000 /* reg value uses param */ > +#define CS_CFG_REG_VAL_MASK 0x04000000 /* reg value bit masked */ > +#define CS_CFG_REG_VAL_64BIT 0x02000000 /* reg value 64 bit */ > +#define CS_CFG_REG_VAL_SAVE 0x01000000 /* reg value save on disable */ > +#define CS_CFG_REG_ID_MASK 0x00000FFF /* reg offset / id in device */ > +#define CS_CFG_REG_DEV_MASK 0x00FFF000 /* device specific flags */ > + > +/* > + * 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 */ > +#define CS_CFG_MATCH_CLASS_CTI_ALL 0x0004 /* match any CTI device */ > +#define CS_CFG_MATCH_CLASS_CTI_CPU 0x0008 > +#define CS_CFG_MATCH_CLASS_CTI_SYS 0x0010 > + > +/* flags defining device instance matching - used in config data. */ > +#define CS_CFG_MATCH_INST_ANY 0x80000000 /* any instance of a class */ > +#define CS_CFG_MATCH_INST_AMBA_DEVICE 0x40000000 /* specific amba device */ > + > +/* > + * 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. > + * > + * Supports full 64 bit register value, or 32 bit value with optional mask > + * value. > + * > + * @flags: define value usage as 32bit, 32bit+mask or 64bit. > + * @val64: 64 bit value. > + * @val32: 32 bit value. > + * @mask32: 32 bit mask when using 32 bit value to access device register. > + */ > +struct cscfg_regval { > + u32 flags; > + union { > + u64 val64; > + struct { > + u32 val32; > + u32 mask32; > + }; > + }; > +}; > + > + > +/** > + * Device feature descriptor - combination of registers and parameters to > + * program a device to implement a specific complex function. > + * > + * @name: feature name. > + * @brief: brief description of the feature. > + * @item: List entry. > + * @match_flags: matching information if loading into a device > + * @nr_params: number of parameters used. > + * @params: array of parameters used. > + * @nr_regs: number of registers used. > + * @reg: array of registers used. > + */ > +struct cscfg_feature_desc { > + const char *name; > + const char *brief; > + struct list_head item; > + u32 match_flags; > + int nr_params; > + struct cscfg_parameter_desc *params; > + int nr_regs; > + struct cscfg_regval *regs; > +}; > + > +/** > + * Device / feature matching information. > + * > + * Used by loading configurations to define which class or specific devices > + * they want to match used features to, and registered devices to specify which > + * matching class and information they support. > + * The load process uses these matching pairs to load feature instances into > + * matching devices. > + * > + * @match_flags: used to match to a particular class of device. > + * @dev_name: used to match to a particular device instance on the system. > + * > + */ > +struct cscfg_match_info { > + u32 match_flags; > + /* unique device name (e.g. amba bus name) for specific device match */ > + const char *dev_name; > +}; > + > +/** > + * Descriptor for features referenced by a configuration. > + * > + * @name: name of feature to use. Match against the @name in struct > + * cscfg_feature_desc. > + * @nr_params: number of parameters the feature has. > + * @match: match info for the feature when used in this configuration - > + * may be all devices of a class or a specific device in that class. > + */ > +struct cscfg_config_feat_ref { > + const char *name; > + int nr_params; > + struct cscfg_match_info match; > +}; > + > +/** > + * Configuration descriptor - describes selectable system configuration. > + * > + * A configuration describes device features in use, and may provide preset > + * values for the parameters in those features. > + * > + * A single set of presets is the sum of the parameters declared by > + * all the features in use - this value is @nr_total_params. > + * > + * @name: name of the configuration - used for selection. > + * @brief: description of the purpose of the configuration. > + * @item: list entry. > + * @nr_refs: Number of features used in this configuration. > + * @refs: references to features used in this configuration.. > + * @nr_presets: Number of sets of presets supplied by this configuration. > + * @nr_total_params: Sum of all parameters declared by used features > + * @presets: Array of preset values. > + * > + */ > +struct cscfg_config_desc { > + const char *name; > + const char *brief; > + struct list_head item; > + int nr_refs; > + struct cscfg_config_feat_ref *refs; > + int nr_presets; > + int nr_total_params; > + const u64 *presets; /* nr_presets * nr_total_params */ > +}; > + > +#endif /* _CORESIGHT_CORESIGHT_CONFIG_H */ > diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c > index 29c83eac3106..481d2b7b6b6f 100644 > --- a/drivers/hwtracing/coresight/coresight-core.c > +++ b/drivers/hwtracing/coresight/coresight-core.c > @@ -21,6 +21,7 @@ > > #include "coresight-etm-perf.h" > #include "coresight-priv.h" > +#include "coresight-syscfg.h" > > static DEFINE_MUTEX(coresight_mutex); > > @@ -1675,13 +1676,22 @@ static int __init coresight_init(void) > > ret = etm_perf_init(); > if (ret) > - bus_unregister(&coresight_bustype); > + goto exit_bus_unregister; > > + /* initialise the coresight syscfg API */ > + ret = cscfg_init(); > + if (!ret) > + return 0; > + > + etm_perf_exit(); > +exit_bus_unregister: > + bus_unregister(&coresight_bustype); > return ret; > } > > static void __exit coresight_exit(void) > { > + cscfg_exit(); > etm_perf_exit(); > bus_unregister(&coresight_bustype); > } > diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c > index bdc34ca449f7..a608081bd446 100644 > --- a/drivers/hwtracing/coresight/coresight-etm-perf.c > +++ b/drivers/hwtracing/coresight/coresight-etm-perf.c > @@ -627,7 +627,7 @@ int __init etm_perf_init(void) > return ret; > } > > -void __exit etm_perf_exit(void) > +void etm_perf_exit(void) > { > perf_pmu_unregister(&etm_pmu); > } > diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.h b/drivers/hwtracing/coresight/coresight-etm-perf.h > index 3e4f2ad5e193..29d90dfeba31 100644 > --- a/drivers/hwtracing/coresight/coresight-etm-perf.h > +++ b/drivers/hwtracing/coresight/coresight-etm-perf.h > @@ -83,6 +83,6 @@ static inline void *etm_perf_sink_config(struct perf_output_handle *handle) > #endif /* CONFIG_CORESIGHT */ > > int __init etm_perf_init(void); > -void __exit etm_perf_exit(void); > +void etm_perf_exit(void); > > #endif > diff --git a/drivers/hwtracing/coresight/coresight-syscfg.c b/drivers/hwtracing/coresight/coresight-syscfg.c > new file mode 100644 > index 000000000000..6f89541af7a0 > --- /dev/null > +++ b/drivers/hwtracing/coresight/coresight-syscfg.c > @@ -0,0 +1,247 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright (c) 2020 Linaro Limited, All rights reserved. > + * Author: Mike Leach <mike.leach@linaro.org> > + */ > + > +#include <linux/platform_device.h> > + > +#include "coresight-config.h" > +#include "coresight-syscfg.h" > + > +/* > + * cscfg_ API manages configurations and features for the entire coresight > + * infrastructure. > + * > + * It allows the loading of configurations and features, and loads these into > + * coresight devices as appropriate. > + */ > + > +static DEFINE_MUTEX(cscfg_mutex); > + > +/* only one of these */ > +static struct cscfg_api_data cscfg_data; > + > +/* get reference to cscfg device */ > +struct device *to_device_cscfg(void); > + > +/* load features and configuations into the lists */ > + > +/* check feature list for a named feature - call with mutex locked. */ > +static bool cscfg_match_list_feat(const char *name) > +{ > + struct cscfg_feature_desc *curr_item; > + > + list_for_each_entry(curr_item, &cscfg_data.feat_list, item) { > + if (strcmp(curr_item->name, name) == 0) > + return true; > + } > + return false; > +} > + > +/* check all feat needed for cfg are in the list - call with mutex locked. */ > +static int cscfg_check_feat_for_cfg(struct cscfg_config_desc *cfg_desc) > +{ > + int i; > + > + for (i = 0; i < cfg_desc->nr_refs; i++) > + if (!cscfg_match_list_feat(cfg_desc->refs[i].name)) > + return -EINVAL; > + return 0; > +} > + > +/* > + * load feature - add to feature list. > + */ > +static int cscfg_load_feat(struct cscfg_feature_desc *feat_desc) > +{ > + list_add(&feat_desc->item, &cscfg_data.feat_list); > + > + return 0; > +} > + > +/* > + * load config into the system - validate used features exist then add to > + * config list. > + */ > +static int cscfg_load_config(struct cscfg_config_desc *cfg_desc) > +{ > + int err; > + > + /* validate features are present */ > + err = cscfg_check_feat_for_cfg(cfg_desc); > + if (err) > + return err; > + > + list_add(&cfg_desc->item, &cscfg_data.config_list); > + > + return 0; > +} > + > +/* > + * External API function to load feature and config sets. > + * Take a 0 terminated array of feature descriptors and/or configuration > + * descriptors and load into the system. > + * Features are loaded first to ensure configuration dependencies can be met. > + */ > +int cscfg_load_config_sets(struct cscfg_config_desc **cfg_descs, > + struct cscfg_feature_desc **feat_descs) > +{ > + int err, i = 0; > + > + mutex_lock(&cscfg_mutex); > + > + /* load features first */ > + if (feat_descs) { > + while (feat_descs[i]) { > + err = cscfg_load_feat(feat_descs[i]); > + if (err) { > + pr_err("coresight-syscfg: Failed to load feature %s\n", > + feat_descs[i]->name); > + goto do_unlock; > + } > + i++; > + } > + } > + > + /* next any configurations to check feature dependencies */ > + i = 0; > + if (cfg_descs) { > + while (cfg_descs[i]) { > + err = cscfg_load_config(cfg_descs[i]); > + if (err) { > + pr_err("coresight-syscfg: Failed to load configuration %s\n", > + cfg_descs[i]->name); > + goto do_unlock; > + } > + i++; > + } > + } > + > +do_unlock: > + mutex_unlock(&cscfg_mutex); > + return err; > +} > +EXPORT_SYMBOL_GPL(cscfg_load_config_sets); > + > +/* Initialise system configuration management driver. */ > +/* only one of these */ > +static struct cscfg_device *cscfg_dev; > + > +/* > + * We have a separate coresight-config bus for the config device so it does > + * not appear on the main coresight bus and affect device searches on that bus. > + */ > +static struct bus_type cscfg_bus_type = { > + .name = "coresight-config", > +}; > + > +struct device *to_device_cscfg(void) > +{ > + return cscfg_dev ? &cscfg_dev->dev : NULL; > +} > + > +/* Must have a release function or the kernel will complain on module unload */ > +void cscfg_dev_release(struct device *dev) > +{ > + kfree(cscfg_dev); > + cscfg_dev = NULL; > +} > + > +int cscfg_create_device(void) > +{ > + struct device *dev; > + int err = -ENOMEM; > + > + mutex_lock(&cscfg_mutex); > + if (cscfg_dev) { > + err = -EINVAL; > + goto create_dev_exit_unlock; > + } > + > + cscfg_dev = kzalloc(sizeof(struct cscfg_device), GFP_KERNEL); > + if (!cscfg_dev) > + goto create_dev_exit_unlock; > + > + /* setup the device */ > + dev = to_device_cscfg(); > + dev->bus = &cscfg_bus_type; > + dev->parent = &platform_bus; > + dev->release = cscfg_dev_release; > + dev->init_name = "system_cfg"; > + cscfg_dev->cfg_data = &cscfg_data; > + > + err = device_register(dev); > + if (err) > + cscfg_dev_release(dev); > + > +create_dev_exit_unlock: > + mutex_unlock(&cscfg_mutex); > + return err; > +} > + > +void cscfg_clear_device(void) > +{ > + mutex_lock(&cscfg_mutex); > + device_unregister(to_device_cscfg()); > + mutex_unlock(&cscfg_mutex); > +} > + > +/* driver initialisation */ > +static struct cscfg_driver cs_config_driver = { > + .drv = { > + .name = "cs-syscfg-drv", > + .owner = THIS_MODULE, > + .suppress_bind_attrs = true, > + }, > +}; > + > +int __init cscfg_driver_init(void) > +{ > + cs_config_driver.drv.bus = &cscfg_bus_type; > + return driver_register(&cs_config_driver.drv); > +} > + > +void cscfg_driver_exit(void) > +{ > + driver_unregister(&cs_config_driver.drv); > +} > + > +/* Initialise system config management API */ > +int __init cscfg_init(void) > +{ > + int err = 0; > + > + err = bus_register(&cscfg_bus_type); > + if (err) > + return err; > + > + err = cscfg_driver_init(); > + if (err) > + goto exit_bus_unregister; > + > + err = cscfg_create_device(); > + if (err) > + goto exit_drv_unregister; > + > + INIT_LIST_HEAD(&cscfg_data.dev_list); > + INIT_LIST_HEAD(&cscfg_data.feat_list); > + INIT_LIST_HEAD(&cscfg_data.config_list); > + cscfg_data.nr_csdev = 0; > + > + dev_info(to_device_cscfg(), "CoreSight Configuration manager initialised"); > + return 0; > + > +exit_drv_unregister: > + cscfg_driver_exit(); > +exit_bus_unregister: > + bus_unregister(&cscfg_bus_type); > + return err; > +} > + > +void __exit cscfg_exit(void) > +{ > + cscfg_clear_device(); > + cscfg_driver_exit(); > + bus_unregister(&cscfg_bus_type); > +} > diff --git a/drivers/hwtracing/coresight/coresight-syscfg.h b/drivers/hwtracing/coresight/coresight-syscfg.h > new file mode 100644 > index 000000000000..5a7896426eab > --- /dev/null > +++ b/drivers/hwtracing/coresight/coresight-syscfg.h > @@ -0,0 +1,57 @@ > +/* SPDX-License-Identifier: GPL-2.0-only */ > +/* > + * Coresight system configuration driver. > + */ > + > +#ifndef CORESIGHT_SYSCFG_H > +#define CORESIGHT_SYSCFG_H > + > +#include <linux/coresight.h> > +#include <linux/device.h> > + > +#include "coresight-config.h" > + > +/** > + * System configuration API data. > + * > + * @dev_list: List of other coresight devices registered with this device. > + * @feat_list: List of features to load into registered devices. > + * @config_list:List of system configurations to load into registered devices. > + * @nr_csdev: Number of registered devices with the cscfg system > + */ > +struct cscfg_api_data { > + struct list_head dev_list; struct list_head csdev_desc_list; And I would rename cscfg_csdev_register to cscfg_csdev_desc in patch 02. > + struct list_head feat_list; struct list_head feat_desc_list; > + struct list_head config_list; struct list_head config_desc_list; That way we know exactly what is enqued. > + int nr_csdev; > +}; > + > +/* internal core operations for cscfg */ > +int __init cscfg_init(void); > +void __exit cscfg_exit(void); > + > +/* syscfg external API */ > +int cscfg_load_config_sets(struct cscfg_config_desc **cfg_descs, > + struct cscfg_feature_desc **feat_descs); > + > +/* system configuration device driver and API */ > +/** > + * System configuration device. > + * > + * Need a device to 'own' some coresight system wide sysfs entries in > + * perf events etc. > + * > + * @dev: The device. > + * @cfg_data: A reference to the configuration and feature lists > + */ > +struct cscfg_device { > + struct device dev; > + struct cscfg_api_data *cfg_data; > +}; > + > +/* basic device driver */ > +struct cscfg_driver { > + struct device_driver drv; > +}; > + > +#endif /* CORESIGHT_SYSCFG_H */ > -- > 2.17.1 >
On Fri, Oct 30, 2020 at 05:56:47PM +0000, Mike Leach wrote: > Creates an system management API to allow complex configurations and > features to be programmed into a CoreSight infrastructure. > > A feature is defined as a programming set for a device or class of > devices. > > A configuration is a set of features across the system that are enabled > for a trace session. > > The API will manage system wide configuration, and allow complex > programmed features to be added to individual device instances, and > provide for system wide configuration selection on trace capture > operations. > > This patch creates the initial data object and the initial API for > loading configurations and features. > > Signed-off-by: Mike Leach <mike.leach@linaro.org> > --- > drivers/hwtracing/coresight/Makefile | 2 +- > .../hwtracing/coresight/coresight-config.h | 170 ++++++++++++ > drivers/hwtracing/coresight/coresight-core.c | 12 +- > .../hwtracing/coresight/coresight-etm-perf.c | 2 +- > .../hwtracing/coresight/coresight-etm-perf.h | 2 +- > .../hwtracing/coresight/coresight-syscfg.c | 247 ++++++++++++++++++ > .../hwtracing/coresight/coresight-syscfg.h | 57 ++++ > 7 files changed, 488 insertions(+), 4 deletions(-) > create mode 100644 drivers/hwtracing/coresight/coresight-config.h > create mode 100644 drivers/hwtracing/coresight/coresight-syscfg.c > create mode 100644 drivers/hwtracing/coresight/coresight-syscfg.h > > diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile > index f20e357758d1..4ce854c434b1 100644 > --- a/drivers/hwtracing/coresight/Makefile > +++ b/drivers/hwtracing/coresight/Makefile > @@ -4,7 +4,7 @@ > # > obj-$(CONFIG_CORESIGHT) += coresight.o > coresight-y := coresight-core.o coresight-etm-perf.o coresight-platform.o \ > - coresight-sysfs.o > + coresight-sysfs.o coresight-syscfg.o > obj-$(CONFIG_CORESIGHT_LINK_AND_SINK_TMC) += coresight-tmc.o > coresight-tmc-y := coresight-tmc-core.o coresight-tmc-etf.o \ > coresight-tmc-etr.o > diff --git a/drivers/hwtracing/coresight/coresight-config.h b/drivers/hwtracing/coresight/coresight-config.h > new file mode 100644 > index 000000000000..0d9ae1dc4517 > --- /dev/null > +++ b/drivers/hwtracing/coresight/coresight-config.h > @@ -0,0 +1,170 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * Copyright (c) 2020 Linaro Limited, All rights reserved. > + * Author: Mike Leach <mike.leach@linaro.org> > + */ > + > +#ifndef _CORESIGHT_CORESIGHT_CONFIG_H > +#define _CORESIGHT_CORESIGHT_CONFIG_H > + > +#include <linux/coresight.h> > +#include <linux/types.h> > + > +/* CoreSight Configuration - complex component and system config handling */ > + > +/* generic register flags */ > +#define CS_CFG_REG_STD 0x80000000 /* reg is standard reg */ > +#define CS_CFG_REG_RESOURCE 0x40000000 /* reg is a resource */ > +#define CS_CFG_REG_VAL_PARAM 0x08000000 /* reg value uses param */ > +#define CS_CFG_REG_VAL_MASK 0x04000000 /* reg value bit masked */ > +#define CS_CFG_REG_VAL_64BIT 0x02000000 /* reg value 64 bit */ > +#define CS_CFG_REG_VAL_SAVE 0x01000000 /* reg value save on disable */ > +#define CS_CFG_REG_ID_MASK 0x00000FFF /* reg offset / id in device */ > +#define CS_CFG_REG_DEV_MASK 0x00FFF000 /* device specific flags */ > + > +/* > + * 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 */ > +#define CS_CFG_MATCH_CLASS_CTI_ALL 0x0004 /* match any CTI device */ > +#define CS_CFG_MATCH_CLASS_CTI_CPU 0x0008 > +#define CS_CFG_MATCH_CLASS_CTI_SYS 0x0010 > + > +/* flags defining device instance matching - used in config data. */ > +#define CS_CFG_MATCH_INST_ANY 0x80000000 /* any instance of a class */ > +#define CS_CFG_MATCH_INST_AMBA_DEVICE 0x40000000 /* specific amba device */ > + > +/* > + * 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. > + * > + * Supports full 64 bit register value, or 32 bit value with optional mask > + * value. > + * > + * @flags: define value usage as 32bit, 32bit+mask or 64bit. > + * @val64: 64 bit value. > + * @val32: 32 bit value. > + * @mask32: 32 bit mask when using 32 bit value to access device register. > + */ > +struct cscfg_regval { > + u32 flags; > + union { > + u64 val64; > + struct { > + u32 val32; > + u32 mask32; > + }; > + }; > +}; > + > + > +/** > + * Device feature descriptor - combination of registers and parameters to > + * program a device to implement a specific complex function. > + * > + * @name: feature name. > + * @brief: brief description of the feature. > + * @item: List entry. > + * @match_flags: matching information if loading into a device > + * @nr_params: number of parameters used. > + * @params: array of parameters used. > + * @nr_regs: number of registers used. > + * @reg: array of registers used. > + */ > +struct cscfg_feature_desc { > + const char *name; > + const char *brief; > + struct list_head item; > + u32 match_flags; > + int nr_params; > + struct cscfg_parameter_desc *params; > + int nr_regs; > + struct cscfg_regval *regs; > +}; > + > +/** > + * Device / feature matching information. > + * > + * Used by loading configurations to define which class or specific devices > + * they want to match used features to, and registered devices to specify which > + * matching class and information they support. > + * The load process uses these matching pairs to load feature instances into > + * matching devices. > + * > + * @match_flags: used to match to a particular class of device. > + * @dev_name: used to match to a particular device instance on the system. > + * > + */ > +struct cscfg_match_info { > + u32 match_flags; > + /* unique device name (e.g. amba bus name) for specific device match */ > + const char *dev_name; > +}; > + > +/** > + * Descriptor for features referenced by a configuration. > + * > + * @name: name of feature to use. Match against the @name in struct > + * cscfg_feature_desc. > + * @nr_params: number of parameters the feature has. > + * @match: match info for the feature when used in this configuration - > + * may be all devices of a class or a specific device in that class. > + */ > +struct cscfg_config_feat_ref { > + const char *name; > + int nr_params; > + struct cscfg_match_info match; > +}; > + > +/** > + * Configuration descriptor - describes selectable system configuration. > + * > + * A configuration describes device features in use, and may provide preset > + * values for the parameters in those features. > + * > + * A single set of presets is the sum of the parameters declared by > + * all the features in use - this value is @nr_total_params. > + * > + * @name: name of the configuration - used for selection. > + * @brief: description of the purpose of the configuration. > + * @item: list entry. > + * @nr_refs: Number of features used in this configuration. > + * @refs: references to features used in this configuration.. > + * @nr_presets: Number of sets of presets supplied by this configuration. > + * @nr_total_params: Sum of all parameters declared by used features > + * @presets: Array of preset values. > + * > + */ > +struct cscfg_config_desc { > + const char *name; > + const char *brief; > + struct list_head item; > + int nr_refs; > + struct cscfg_config_feat_ref *refs; > + int nr_presets; > + int nr_total_params; > + const u64 *presets; /* nr_presets * nr_total_params */ > +}; > + > +#endif /* _CORESIGHT_CORESIGHT_CONFIG_H */ > diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c > index 29c83eac3106..481d2b7b6b6f 100644 > --- a/drivers/hwtracing/coresight/coresight-core.c > +++ b/drivers/hwtracing/coresight/coresight-core.c > @@ -21,6 +21,7 @@ > > #include "coresight-etm-perf.h" > #include "coresight-priv.h" > +#include "coresight-syscfg.h" > > static DEFINE_MUTEX(coresight_mutex); > > @@ -1675,13 +1676,22 @@ static int __init coresight_init(void) > > ret = etm_perf_init(); > if (ret) > - bus_unregister(&coresight_bustype); > + goto exit_bus_unregister; > > + /* initialise the coresight syscfg API */ > + ret = cscfg_init(); > + if (!ret) > + return 0; > + > + etm_perf_exit(); > +exit_bus_unregister: > + bus_unregister(&coresight_bustype); > return ret; > } > > static void __exit coresight_exit(void) > { > + cscfg_exit(); > etm_perf_exit(); > bus_unregister(&coresight_bustype); > } > diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c > index bdc34ca449f7..a608081bd446 100644 > --- a/drivers/hwtracing/coresight/coresight-etm-perf.c > +++ b/drivers/hwtracing/coresight/coresight-etm-perf.c > @@ -627,7 +627,7 @@ int __init etm_perf_init(void) > return ret; > } > > -void __exit etm_perf_exit(void) > +void etm_perf_exit(void) > { > perf_pmu_unregister(&etm_pmu); > } > diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.h b/drivers/hwtracing/coresight/coresight-etm-perf.h > index 3e4f2ad5e193..29d90dfeba31 100644 > --- a/drivers/hwtracing/coresight/coresight-etm-perf.h > +++ b/drivers/hwtracing/coresight/coresight-etm-perf.h > @@ -83,6 +83,6 @@ static inline void *etm_perf_sink_config(struct perf_output_handle *handle) > #endif /* CONFIG_CORESIGHT */ > > int __init etm_perf_init(void); > -void __exit etm_perf_exit(void); > +void etm_perf_exit(void); > > #endif > diff --git a/drivers/hwtracing/coresight/coresight-syscfg.c b/drivers/hwtracing/coresight/coresight-syscfg.c > new file mode 100644 > index 000000000000..6f89541af7a0 > --- /dev/null > +++ b/drivers/hwtracing/coresight/coresight-syscfg.c > @@ -0,0 +1,247 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright (c) 2020 Linaro Limited, All rights reserved. > + * Author: Mike Leach <mike.leach@linaro.org> > + */ > + > +#include <linux/platform_device.h> > + > +#include "coresight-config.h" > +#include "coresight-syscfg.h" > + > +/* > + * cscfg_ API manages configurations and features for the entire coresight > + * infrastructure. > + * > + * It allows the loading of configurations and features, and loads these into > + * coresight devices as appropriate. > + */ > + > +static DEFINE_MUTEX(cscfg_mutex); > + > +/* only one of these */ > +static struct cscfg_api_data cscfg_data; > + > +/* get reference to cscfg device */ > +struct device *to_device_cscfg(void); > + > +/* load features and configuations into the lists */ > + > +/* check feature list for a named feature - call with mutex locked. */ > +static bool cscfg_match_list_feat(const char *name) > +{ > + struct cscfg_feature_desc *curr_item; > + > + list_for_each_entry(curr_item, &cscfg_data.feat_list, item) { > + if (strcmp(curr_item->name, name) == 0) > + return true; > + } > + return false; > +} > + > +/* check all feat needed for cfg are in the list - call with mutex locked. */ > +static int cscfg_check_feat_for_cfg(struct cscfg_config_desc *cfg_desc) > +{ > + int i; > + > + for (i = 0; i < cfg_desc->nr_refs; i++) > + if (!cscfg_match_list_feat(cfg_desc->refs[i].name)) > + return -EINVAL; > + return 0; > +} > + > +/* > + * load feature - add to feature list. > + */ > +static int cscfg_load_feat(struct cscfg_feature_desc *feat_desc) > +{ > + list_add(&feat_desc->item, &cscfg_data.feat_list); > + > + return 0; > +} > + > +/* > + * load config into the system - validate used features exist then add to > + * config list. > + */ > +static int cscfg_load_config(struct cscfg_config_desc *cfg_desc) > +{ > + int err; > + > + /* validate features are present */ > + err = cscfg_check_feat_for_cfg(cfg_desc); > + if (err) > + return err; > + > + list_add(&cfg_desc->item, &cscfg_data.config_list); > + > + return 0; > +} > + > +/* > + * External API function to load feature and config sets. > + * Take a 0 terminated array of feature descriptors and/or configuration > + * descriptors and load into the system. > + * Features are loaded first to ensure configuration dependencies can be met. > + */ > +int cscfg_load_config_sets(struct cscfg_config_desc **cfg_descs, > + struct cscfg_feature_desc **feat_descs) > +{ > + int err, i = 0; > + > + mutex_lock(&cscfg_mutex); > + > + /* load features first */ > + if (feat_descs) { > + while (feat_descs[i]) { > + err = cscfg_load_feat(feat_descs[i]); > + if (err) { > + pr_err("coresight-syscfg: Failed to load feature %s\n", > + feat_descs[i]->name); > + goto do_unlock; > + } > + i++; > + } > + } > + > + /* next any configurations to check feature dependencies */ > + i = 0; > + if (cfg_descs) { > + while (cfg_descs[i]) { > + err = cscfg_load_config(cfg_descs[i]); > + if (err) { > + pr_err("coresight-syscfg: Failed to load configuration %s\n", > + cfg_descs[i]->name); > + goto do_unlock; > + } > + i++; > + } > + } > + > +do_unlock: > + mutex_unlock(&cscfg_mutex); > + return err; > +} > +EXPORT_SYMBOL_GPL(cscfg_load_config_sets); > + > +/* Initialise system configuration management driver. */ > +/* only one of these */ > +static struct cscfg_device *cscfg_dev; > + > +/* > + * We have a separate coresight-config bus for the config device so it does > + * not appear on the main coresight bus and affect device searches on that bus. > + */ > +static struct bus_type cscfg_bus_type = { > + .name = "coresight-config", > +}; > + > +struct device *to_device_cscfg(void) > +{ > + return cscfg_dev ? &cscfg_dev->dev : NULL; > +} > + > +/* Must have a release function or the kernel will complain on module unload */ > +void cscfg_dev_release(struct device *dev) > +{ > + kfree(cscfg_dev); > + cscfg_dev = NULL; > +} > + > +int cscfg_create_device(void) > +{ > + struct device *dev; > + int err = -ENOMEM; > + > + mutex_lock(&cscfg_mutex); > + if (cscfg_dev) { > + err = -EINVAL; > + goto create_dev_exit_unlock; > + } > + > + cscfg_dev = kzalloc(sizeof(struct cscfg_device), GFP_KERNEL); > + if (!cscfg_dev) > + goto create_dev_exit_unlock; > + > + /* setup the device */ > + dev = to_device_cscfg(); > + dev->bus = &cscfg_bus_type; > + dev->parent = &platform_bus; cscfg_dev.dev doesn't have to be on a bus, nor does it need to have the platform_bus as a parent. > + dev->release = cscfg_dev_release; > + dev->init_name = "system_cfg"; > + cscfg_dev->cfg_data = &cscfg_data; > + > + err = device_register(dev); > + if (err) > + cscfg_dev_release(dev); > + > +create_dev_exit_unlock: > + mutex_unlock(&cscfg_mutex); > + return err; > +} > + > +void cscfg_clear_device(void) > +{ > + mutex_lock(&cscfg_mutex); > + device_unregister(to_device_cscfg()); > + mutex_unlock(&cscfg_mutex); > +} > + > +/* driver initialisation */ > +static struct cscfg_driver cs_config_driver = { > + .drv = { > + .name = "cs-syscfg-drv", > + .owner = THIS_MODULE, > + .suppress_bind_attrs = true, > + }, > +}; > + > +int __init cscfg_driver_init(void) > +{ > + cs_config_driver.drv.bus = &cscfg_bus_type; > + return driver_register(&cs_config_driver.drv); > +} As far as I can tell no device is using the cs_config_driver. I'm also don't understand the scenario where seeing the system_cfg device under the coresight-config bus is useful for users. More on that front below. > + > +void cscfg_driver_exit(void) > +{ > + driver_unregister(&cs_config_driver.drv); > +} > + > +/* Initialise system config management API */ > +int __init cscfg_init(void) > +{ > + int err = 0; > + > + err = bus_register(&cscfg_bus_type); > + if (err) > + return err; > + > + err = cscfg_driver_init(); > + if (err) > + goto exit_bus_unregister; > + Convinced I was missing something big I applied all the patches in this set and commented out the bus_register() and cscfg_driver_init() above. I also commented out dev->bus and dev->parent in cscfg_create_device(). Everything compiled and I couldn't find a difference in terms of functionality. To me the configuration manager should be a library available to the rest of the coresight framework. In fact after removing the above that is exactly what it becomes. > + err = cscfg_create_device(); > + if (err) > + goto exit_drv_unregister; > + > + INIT_LIST_HEAD(&cscfg_data.dev_list); > + INIT_LIST_HEAD(&cscfg_data.feat_list); > + INIT_LIST_HEAD(&cscfg_data.config_list); > + cscfg_data.nr_csdev = 0; > + > + dev_info(to_device_cscfg(), "CoreSight Configuration manager initialised"); > + return 0; > + > +exit_drv_unregister: > + cscfg_driver_exit(); > +exit_bus_unregister: > + bus_unregister(&cscfg_bus_type); > + return err; > +} > + > +void __exit cscfg_exit(void) > +{ > + cscfg_clear_device(); > + cscfg_driver_exit(); > + bus_unregister(&cscfg_bus_type); > +} > diff --git a/drivers/hwtracing/coresight/coresight-syscfg.h b/drivers/hwtracing/coresight/coresight-syscfg.h > new file mode 100644 > index 000000000000..5a7896426eab > --- /dev/null > +++ b/drivers/hwtracing/coresight/coresight-syscfg.h > @@ -0,0 +1,57 @@ > +/* SPDX-License-Identifier: GPL-2.0-only */ > +/* > + * Coresight system configuration driver. > + */ > + > +#ifndef CORESIGHT_SYSCFG_H > +#define CORESIGHT_SYSCFG_H > + > +#include <linux/coresight.h> > +#include <linux/device.h> > + > +#include "coresight-config.h" > + > +/** > + * System configuration API data. > + * > + * @dev_list: List of other coresight devices registered with this device. > + * @feat_list: List of features to load into registered devices. > + * @config_list:List of system configurations to load into registered devices. > + * @nr_csdev: Number of registered devices with the cscfg system > + */ > +struct cscfg_api_data { > + struct list_head dev_list; > + struct list_head feat_list; > + struct list_head config_list; > + int nr_csdev; > +}; > + > +/* internal core operations for cscfg */ > +int __init cscfg_init(void); > +void __exit cscfg_exit(void); > + > +/* syscfg external API */ > +int cscfg_load_config_sets(struct cscfg_config_desc **cfg_descs, > + struct cscfg_feature_desc **feat_descs); > + > +/* system configuration device driver and API */ > +/** > + * System configuration device. > + * > + * Need a device to 'own' some coresight system wide sysfs entries in > + * perf events etc. > + * > + * @dev: The device. > + * @cfg_data: A reference to the configuration and feature lists > + */ > +struct cscfg_device { > + struct device dev; > + struct cscfg_api_data *cfg_data; > +}; > + > +/* basic device driver */ > +struct cscfg_driver { > + struct device_driver drv; > +}; > + > +#endif /* CORESIGHT_SYSCFG_H */ > -- > 2.17.1 >
HI Mathieu, Followed pretty much all of your suggestions here - and in prior comments on this patch. On Thu, 26 Nov 2020 at 18:35, Mathieu Poirier <mathieu.poirier@linaro.org> wrote: > > On Fri, Oct 30, 2020 at 05:56:47PM +0000, Mike Leach wrote: > > Creates an system management API to allow complex configurations and > > features to be programmed into a CoreSight infrastructure. > > > > A feature is defined as a programming set for a device or class of > > devices. > > > > A configuration is a set of features across the system that are enabled > > for a trace session. > > > > The API will manage system wide configuration, and allow complex > > programmed features to be added to individual device instances, and > > provide for system wide configuration selection on trace capture > > operations. > > > > This patch creates the initial data object and the initial API for > > loading configurations and features. > > > > Signed-off-by: Mike Leach <mike.leach@linaro.org> > > --- > > drivers/hwtracing/coresight/Makefile | 2 +- > > .../hwtracing/coresight/coresight-config.h | 170 ++++++++++++ > > drivers/hwtracing/coresight/coresight-core.c | 12 +- > > .../hwtracing/coresight/coresight-etm-perf.c | 2 +- > > .../hwtracing/coresight/coresight-etm-perf.h | 2 +- > > .../hwtracing/coresight/coresight-syscfg.c | 247 ++++++++++++++++++ > > .../hwtracing/coresight/coresight-syscfg.h | 57 ++++ > > 7 files changed, 488 insertions(+), 4 deletions(-) > > create mode 100644 drivers/hwtracing/coresight/coresight-config.h > > create mode 100644 drivers/hwtracing/coresight/coresight-syscfg.c > > create mode 100644 drivers/hwtracing/coresight/coresight-syscfg.h > > > > diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile > > index f20e357758d1..4ce854c434b1 100644 > > --- a/drivers/hwtracing/coresight/Makefile > > +++ b/drivers/hwtracing/coresight/Makefile > > @@ -4,7 +4,7 @@ > > # > > obj-$(CONFIG_CORESIGHT) += coresight.o > > coresight-y := coresight-core.o coresight-etm-perf.o coresight-platform.o \ > > - coresight-sysfs.o > > + coresight-sysfs.o coresight-syscfg.o > > obj-$(CONFIG_CORESIGHT_LINK_AND_SINK_TMC) += coresight-tmc.o > > coresight-tmc-y := coresight-tmc-core.o coresight-tmc-etf.o \ > > coresight-tmc-etr.o > > diff --git a/drivers/hwtracing/coresight/coresight-config.h b/drivers/hwtracing/coresight/coresight-config.h > > new file mode 100644 > > index 000000000000..0d9ae1dc4517 > > --- /dev/null > > +++ b/drivers/hwtracing/coresight/coresight-config.h > > @@ -0,0 +1,170 @@ > > +/* SPDX-License-Identifier: GPL-2.0 */ > > +/* > > + * Copyright (c) 2020 Linaro Limited, All rights reserved. > > + * Author: Mike Leach <mike.leach@linaro.org> > > + */ > > + > > +#ifndef _CORESIGHT_CORESIGHT_CONFIG_H > > +#define _CORESIGHT_CORESIGHT_CONFIG_H > > + > > +#include <linux/coresight.h> > > +#include <linux/types.h> > > + > > +/* CoreSight Configuration - complex component and system config handling */ > > + > > +/* generic register flags */ > > +#define CS_CFG_REG_STD 0x80000000 /* reg is standard reg */ > > +#define CS_CFG_REG_RESOURCE 0x40000000 /* reg is a resource */ > > +#define CS_CFG_REG_VAL_PARAM 0x08000000 /* reg value uses param */ > > +#define CS_CFG_REG_VAL_MASK 0x04000000 /* reg value bit masked */ > > +#define CS_CFG_REG_VAL_64BIT 0x02000000 /* reg value 64 bit */ > > +#define CS_CFG_REG_VAL_SAVE 0x01000000 /* reg value save on disable */ > > +#define CS_CFG_REG_ID_MASK 0x00000FFF /* reg offset / id in device */ > > +#define CS_CFG_REG_DEV_MASK 0x00FFF000 /* device specific flags */ > > + > > +/* > > + * 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 */ > > +#define CS_CFG_MATCH_CLASS_CTI_ALL 0x0004 /* match any CTI device */ > > +#define CS_CFG_MATCH_CLASS_CTI_CPU 0x0008 > > +#define CS_CFG_MATCH_CLASS_CTI_SYS 0x0010 > > + > > +/* flags defining device instance matching - used in config data. */ > > +#define CS_CFG_MATCH_INST_ANY 0x80000000 /* any instance of a class */ > > +#define CS_CFG_MATCH_INST_AMBA_DEVICE 0x40000000 /* specific amba device */ > > + > > +/* > > + * 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. > > + * > > + * Supports full 64 bit register value, or 32 bit value with optional mask > > + * value. > > + * > > + * @flags: define value usage as 32bit, 32bit+mask or 64bit. > > + * @val64: 64 bit value. > > + * @val32: 32 bit value. > > + * @mask32: 32 bit mask when using 32 bit value to access device register. > > + */ > > +struct cscfg_regval { > > + u32 flags; > > + union { > > + u64 val64; > > + struct { > > + u32 val32; > > + u32 mask32; > > + }; > > + }; > > +}; > > + > > + > > +/** > > + * Device feature descriptor - combination of registers and parameters to > > + * program a device to implement a specific complex function. > > + * > > + * @name: feature name. > > + * @brief: brief description of the feature. > > + * @item: List entry. > > + * @match_flags: matching information if loading into a device > > + * @nr_params: number of parameters used. > > + * @params: array of parameters used. > > + * @nr_regs: number of registers used. > > + * @reg: array of registers used. > > + */ > > +struct cscfg_feature_desc { > > + const char *name; > > + const char *brief; > > + struct list_head item; > > + u32 match_flags; > > + int nr_params; > > + struct cscfg_parameter_desc *params; > > + int nr_regs; > > + struct cscfg_regval *regs; > > +}; > > + > > +/** > > + * Device / feature matching information. > > + * > > + * Used by loading configurations to define which class or specific devices > > + * they want to match used features to, and registered devices to specify which > > + * matching class and information they support. > > + * The load process uses these matching pairs to load feature instances into > > + * matching devices. > > + * > > + * @match_flags: used to match to a particular class of device. > > + * @dev_name: used to match to a particular device instance on the system. > > + * > > + */ > > +struct cscfg_match_info { > > + u32 match_flags; > > + /* unique device name (e.g. amba bus name) for specific device match */ > > + const char *dev_name; > > +}; > > + > > +/** > > + * Descriptor for features referenced by a configuration. > > + * > > + * @name: name of feature to use. Match against the @name in struct > > + * cscfg_feature_desc. > > + * @nr_params: number of parameters the feature has. > > + * @match: match info for the feature when used in this configuration - > > + * may be all devices of a class or a specific device in that class. > > + */ > > +struct cscfg_config_feat_ref { > > + const char *name; > > + int nr_params; > > + struct cscfg_match_info match; > > +}; > > + > > +/** > > + * Configuration descriptor - describes selectable system configuration. > > + * > > + * A configuration describes device features in use, and may provide preset > > + * values for the parameters in those features. > > + * > > + * A single set of presets is the sum of the parameters declared by > > + * all the features in use - this value is @nr_total_params. > > + * > > + * @name: name of the configuration - used for selection. > > + * @brief: description of the purpose of the configuration. > > + * @item: list entry. > > + * @nr_refs: Number of features used in this configuration. > > + * @refs: references to features used in this configuration.. > > + * @nr_presets: Number of sets of presets supplied by this configuration. > > + * @nr_total_params: Sum of all parameters declared by used features > > + * @presets: Array of preset values. > > + * > > + */ > > +struct cscfg_config_desc { > > + const char *name; > > + const char *brief; > > + struct list_head item; > > + int nr_refs; > > + struct cscfg_config_feat_ref *refs; > > + int nr_presets; > > + int nr_total_params; > > + const u64 *presets; /* nr_presets * nr_total_params */ > > +}; > > + > > +#endif /* _CORESIGHT_CORESIGHT_CONFIG_H */ > > diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c > > index 29c83eac3106..481d2b7b6b6f 100644 > > --- a/drivers/hwtracing/coresight/coresight-core.c > > +++ b/drivers/hwtracing/coresight/coresight-core.c > > @@ -21,6 +21,7 @@ > > > > #include "coresight-etm-perf.h" > > #include "coresight-priv.h" > > +#include "coresight-syscfg.h" > > > > static DEFINE_MUTEX(coresight_mutex); > > > > @@ -1675,13 +1676,22 @@ static int __init coresight_init(void) > > > > ret = etm_perf_init(); > > if (ret) > > - bus_unregister(&coresight_bustype); > > + goto exit_bus_unregister; > > > > + /* initialise the coresight syscfg API */ > > + ret = cscfg_init(); > > + if (!ret) > > + return 0; > > + > > + etm_perf_exit(); > > +exit_bus_unregister: > > + bus_unregister(&coresight_bustype); > > return ret; > > } > > > > static void __exit coresight_exit(void) > > { > > + cscfg_exit(); > > etm_perf_exit(); > > bus_unregister(&coresight_bustype); > > } > > diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c > > index bdc34ca449f7..a608081bd446 100644 > > --- a/drivers/hwtracing/coresight/coresight-etm-perf.c > > +++ b/drivers/hwtracing/coresight/coresight-etm-perf.c > > @@ -627,7 +627,7 @@ int __init etm_perf_init(void) > > return ret; > > } > > > > -void __exit etm_perf_exit(void) > > +void etm_perf_exit(void) > > { > > perf_pmu_unregister(&etm_pmu); > > } > > diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.h b/drivers/hwtracing/coresight/coresight-etm-perf.h > > index 3e4f2ad5e193..29d90dfeba31 100644 > > --- a/drivers/hwtracing/coresight/coresight-etm-perf.h > > +++ b/drivers/hwtracing/coresight/coresight-etm-perf.h > > @@ -83,6 +83,6 @@ static inline void *etm_perf_sink_config(struct perf_output_handle *handle) > > #endif /* CONFIG_CORESIGHT */ > > > > int __init etm_perf_init(void); > > -void __exit etm_perf_exit(void); > > +void etm_perf_exit(void); > > > > #endif > > diff --git a/drivers/hwtracing/coresight/coresight-syscfg.c b/drivers/hwtracing/coresight/coresight-syscfg.c > > new file mode 100644 > > index 000000000000..6f89541af7a0 > > --- /dev/null > > +++ b/drivers/hwtracing/coresight/coresight-syscfg.c > > @@ -0,0 +1,247 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > +/* > > + * Copyright (c) 2020 Linaro Limited, All rights reserved. > > + * Author: Mike Leach <mike.leach@linaro.org> > > + */ > > + > > +#include <linux/platform_device.h> > > + > > +#include "coresight-config.h" > > +#include "coresight-syscfg.h" > > + > > +/* > > + * cscfg_ API manages configurations and features for the entire coresight > > + * infrastructure. > > + * > > + * It allows the loading of configurations and features, and loads these into > > + * coresight devices as appropriate. > > + */ > > + > > +static DEFINE_MUTEX(cscfg_mutex); > > + > > +/* only one of these */ > > +static struct cscfg_api_data cscfg_data; > > + > > +/* get reference to cscfg device */ > > +struct device *to_device_cscfg(void); > > + > > +/* load features and configuations into the lists */ > > + > > +/* check feature list for a named feature - call with mutex locked. */ > > +static bool cscfg_match_list_feat(const char *name) > > +{ > > + struct cscfg_feature_desc *curr_item; > > + > > + list_for_each_entry(curr_item, &cscfg_data.feat_list, item) { > > + if (strcmp(curr_item->name, name) == 0) > > + return true; > > + } > > + return false; > > +} > > + > > +/* check all feat needed for cfg are in the list - call with mutex locked. */ > > +static int cscfg_check_feat_for_cfg(struct cscfg_config_desc *cfg_desc) > > +{ > > + int i; > > + > > + for (i = 0; i < cfg_desc->nr_refs; i++) > > + if (!cscfg_match_list_feat(cfg_desc->refs[i].name)) > > + return -EINVAL; > > + return 0; > > +} > > + > > +/* > > + * load feature - add to feature list. > > + */ > > +static int cscfg_load_feat(struct cscfg_feature_desc *feat_desc) > > +{ > > + list_add(&feat_desc->item, &cscfg_data.feat_list); > > + > > + return 0; > > +} > > + > > +/* > > + * load config into the system - validate used features exist then add to > > + * config list. > > + */ > > +static int cscfg_load_config(struct cscfg_config_desc *cfg_desc) > > +{ > > + int err; > > + > > + /* validate features are present */ > > + err = cscfg_check_feat_for_cfg(cfg_desc); > > + if (err) > > + return err; > > + > > + list_add(&cfg_desc->item, &cscfg_data.config_list); > > + > > + return 0; > > +} > > + > > +/* > > + * External API function to load feature and config sets. > > + * Take a 0 terminated array of feature descriptors and/or configuration > > + * descriptors and load into the system. > > + * Features are loaded first to ensure configuration dependencies can be met. > > + */ > > +int cscfg_load_config_sets(struct cscfg_config_desc **cfg_descs, > > + struct cscfg_feature_desc **feat_descs) > > +{ > > + int err, i = 0; > > + > > + mutex_lock(&cscfg_mutex); > > + > > + /* load features first */ > > + if (feat_descs) { > > + while (feat_descs[i]) { > > + err = cscfg_load_feat(feat_descs[i]); > > + if (err) { > > + pr_err("coresight-syscfg: Failed to load feature %s\n", > > + feat_descs[i]->name); > > + goto do_unlock; > > + } > > + i++; > > + } > > + } > > + > > + /* next any configurations to check feature dependencies */ > > + i = 0; > > + if (cfg_descs) { > > + while (cfg_descs[i]) { > > + err = cscfg_load_config(cfg_descs[i]); > > + if (err) { > > + pr_err("coresight-syscfg: Failed to load configuration %s\n", > > + cfg_descs[i]->name); > > + goto do_unlock; > > + } > > + i++; > > + } > > + } > > + > > +do_unlock: > > + mutex_unlock(&cscfg_mutex); > > + return err; > > +} > > +EXPORT_SYMBOL_GPL(cscfg_load_config_sets); > > + > > +/* Initialise system configuration management driver. */ > > +/* only one of these */ > > +static struct cscfg_device *cscfg_dev; > > + > > +/* > > + * We have a separate coresight-config bus for the config device so it does > > + * not appear on the main coresight bus and affect device searches on that bus. > > + */ > > +static struct bus_type cscfg_bus_type = { > > + .name = "coresight-config", > > +}; > > + > > +struct device *to_device_cscfg(void) > > +{ > > + return cscfg_dev ? &cscfg_dev->dev : NULL; > > +} > > + > > +/* Must have a release function or the kernel will complain on module unload */ > > +void cscfg_dev_release(struct device *dev) > > +{ > > + kfree(cscfg_dev); > > + cscfg_dev = NULL; > > +} > > + > > +int cscfg_create_device(void) > > +{ > > + struct device *dev; > > + int err = -ENOMEM; > > + > > + mutex_lock(&cscfg_mutex); > > + if (cscfg_dev) { > > + err = -EINVAL; > > + goto create_dev_exit_unlock; > > + } > > + > > + cscfg_dev = kzalloc(sizeof(struct cscfg_device), GFP_KERNEL); > > + if (!cscfg_dev) > > + goto create_dev_exit_unlock; > > + > > + /* setup the device */ > > + dev = to_device_cscfg(); > > + dev->bus = &cscfg_bus_type; > > + dev->parent = &platform_bus; > > cscfg_dev.dev doesn't have to be on a bus, nor does it need to have the > platform_bus as a parent. > > > + dev->release = cscfg_dev_release; > > + dev->init_name = "system_cfg"; > > + cscfg_dev->cfg_data = &cscfg_data; > > + > > + err = device_register(dev); > > + if (err) > > + cscfg_dev_release(dev); > > + > > +create_dev_exit_unlock: > > + mutex_unlock(&cscfg_mutex); > > + return err; > > +} > > + > > +void cscfg_clear_device(void) > > +{ > > + mutex_lock(&cscfg_mutex); > > + device_unregister(to_device_cscfg()); > > + mutex_unlock(&cscfg_mutex); > > +} > > + > > +/* driver initialisation */ > > +static struct cscfg_driver cs_config_driver = { > > + .drv = { > > + .name = "cs-syscfg-drv", > > + .owner = THIS_MODULE, > > + .suppress_bind_attrs = true, > > + }, > > +}; > > + > > +int __init cscfg_driver_init(void) > > +{ > > + cs_config_driver.drv.bus = &cscfg_bus_type; > > + return driver_register(&cs_config_driver.drv); > > +} > > As far as I can tell no device is using the cs_config_driver. I'm also don't > understand the scenario where seeing the system_cfg device under the > coresight-config bus is useful for users. More on that front below. > Probably isn't - was initially useful for me debugging - but not now. > > + > > +void cscfg_driver_exit(void) > > +{ > > + driver_unregister(&cs_config_driver.drv); > > +} > > + > > +/* Initialise system config management API */ > > +int __init cscfg_init(void) > > +{ > > + int err = 0; > > + > > + err = bus_register(&cscfg_bus_type); > > + if (err) > > + return err; > > + > > + err = cscfg_driver_init(); > > + if (err) > > + goto exit_bus_unregister; > > + > > Convinced I was missing something big I applied all the patches in this set and > commented out the bus_register() and cscfg_driver_init() above. I also > commented out dev->bus and dev->parent in cscfg_create_device(). Everything > compiled and I couldn't find a difference in terms of functionality. > > To me the configuration manager should be a library available to the rest of the > coresight framework. In fact after removing the above that is exactly what it > becomes. > Agreed. The device is there to "own" certain kernel elements such as the sysfs entries in the perf handling in the later patches of this set, but no need for bus ./ driver. The only reason they were there was the fact I assumed they needed to be based on the rest of the driver structures - I couldn't find a concrete example of a virtual device existing in isolation. however, it works just fine without the bus / driver refs so dropped for the next set. In a previous mail you said "In this patchset the presets are easy because autofdo has a single feature and there is only 2 parameters for this feature. I worry about what things will look like when a configuration has 6 featurse, each with a varying number of parameters. Here too I don't have a clear answer on how to proceed but it will need to be revised. " Things will look very much the same. Each row in the preset value array is an ordered list of parameter values, based on the order of features referenced in the configuration, and the order of the parameters in the feature. And the more parameters / features are in a configuration, the more useful preset sets become. Realistically, I do not envisage huge rows of parameters in a configuration - the more degrees of freedom, then the harder it is to understand and use. I would expect users to ultimately write more than one feature / configuration and allow a small number of adjustable parameters, sufficient for the test at hand. And even with the ETM - there is a limit to the number of settings that are usefully variable at runtime. I am open to suggestions for a better representation - but it would need to be flexible enough to be declared as a static structure for compliation in C, and also be easy to index in terms of the code used to set up the preset values when chosen. > > + err = cscfg_create_device(); > > + if (err) > > + goto exit_drv_unregister; > > + > > + INIT_LIST_HEAD(&cscfg_data.dev_list); > > + INIT_LIST_HEAD(&cscfg_data.feat_list); > > + INIT_LIST_HEAD(&cscfg_data.config_list); > > + cscfg_data.nr_csdev = 0; > > + > > + dev_info(to_device_cscfg(), "CoreSight Configuration manager initialised"); > > + return 0; > > + > > +exit_drv_unregister: > > + cscfg_driver_exit(); > > +exit_bus_unregister: > > + bus_unregister(&cscfg_bus_type); > > + return err; > > +} > > + > > +void __exit cscfg_exit(void) > > +{ > > + cscfg_clear_device(); > > + cscfg_driver_exit(); > > + bus_unregister(&cscfg_bus_type); > > +} > > diff --git a/drivers/hwtracing/coresight/coresight-syscfg.h b/drivers/hwtracing/coresight/coresight-syscfg.h > > new file mode 100644 > > index 000000000000..5a7896426eab > > --- /dev/null > > +++ b/drivers/hwtracing/coresight/coresight-syscfg.h > > @@ -0,0 +1,57 @@ > > +/* SPDX-License-Identifier: GPL-2.0-only */ > > +/* > > + * Coresight system configuration driver. > > + */ > > + > > +#ifndef CORESIGHT_SYSCFG_H > > +#define CORESIGHT_SYSCFG_H > > + > > +#include <linux/coresight.h> > > +#include <linux/device.h> > > + > > +#include "coresight-config.h" > > + > > +/** > > + * System configuration API data. > > + * > > + * @dev_list: List of other coresight devices registered with this device. > > + * @feat_list: List of features to load into registered devices. > > + * @config_list:List of system configurations to load into registered devices. > > + * @nr_csdev: Number of registered devices with the cscfg system > > + */ > > +struct cscfg_api_data { > > + struct list_head dev_list; > > + struct list_head feat_list; > > + struct list_head config_list; > > + int nr_csdev; > > +}; > > + > > +/* internal core operations for cscfg */ > > +int __init cscfg_init(void); > > +void __exit cscfg_exit(void); > > + > > +/* syscfg external API */ > > +int cscfg_load_config_sets(struct cscfg_config_desc **cfg_descs, > > + struct cscfg_feature_desc **feat_descs); > > + > > +/* system configuration device driver and API */ > > +/** > > + * System configuration device. > > + * > > + * Need a device to 'own' some coresight system wide sysfs entries in > > + * perf events etc. > > + * > > + * @dev: The device. > > + * @cfg_data: A reference to the configuration and feature lists > > + */ > > +struct cscfg_device { > > + struct device dev; > > + struct cscfg_api_data *cfg_data; > > +}; > > + > > +/* basic device driver */ > > +struct cscfg_driver { > > + struct device_driver drv; > > +}; > > + > > +#endif /* CORESIGHT_SYSCFG_H */ > > -- > > 2.17.1 > > -- Mike Leach Principal Engineer, ARM Ltd. Manchester Design Centre. UK
diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile index f20e357758d1..4ce854c434b1 100644 --- a/drivers/hwtracing/coresight/Makefile +++ b/drivers/hwtracing/coresight/Makefile @@ -4,7 +4,7 @@ # obj-$(CONFIG_CORESIGHT) += coresight.o coresight-y := coresight-core.o coresight-etm-perf.o coresight-platform.o \ - coresight-sysfs.o + coresight-sysfs.o coresight-syscfg.o obj-$(CONFIG_CORESIGHT_LINK_AND_SINK_TMC) += coresight-tmc.o coresight-tmc-y := coresight-tmc-core.o coresight-tmc-etf.o \ coresight-tmc-etr.o diff --git a/drivers/hwtracing/coresight/coresight-config.h b/drivers/hwtracing/coresight/coresight-config.h new file mode 100644 index 000000000000..0d9ae1dc4517 --- /dev/null +++ b/drivers/hwtracing/coresight/coresight-config.h @@ -0,0 +1,170 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 Linaro Limited, All rights reserved. + * Author: Mike Leach <mike.leach@linaro.org> + */ + +#ifndef _CORESIGHT_CORESIGHT_CONFIG_H +#define _CORESIGHT_CORESIGHT_CONFIG_H + +#include <linux/coresight.h> +#include <linux/types.h> + +/* CoreSight Configuration - complex component and system config handling */ + +/* generic register flags */ +#define CS_CFG_REG_STD 0x80000000 /* reg is standard reg */ +#define CS_CFG_REG_RESOURCE 0x40000000 /* reg is a resource */ +#define CS_CFG_REG_VAL_PARAM 0x08000000 /* reg value uses param */ +#define CS_CFG_REG_VAL_MASK 0x04000000 /* reg value bit masked */ +#define CS_CFG_REG_VAL_64BIT 0x02000000 /* reg value 64 bit */ +#define CS_CFG_REG_VAL_SAVE 0x01000000 /* reg value save on disable */ +#define CS_CFG_REG_ID_MASK 0x00000FFF /* reg offset / id in device */ +#define CS_CFG_REG_DEV_MASK 0x00FFF000 /* device specific flags */ + +/* + * 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 */ +#define CS_CFG_MATCH_CLASS_CTI_ALL 0x0004 /* match any CTI device */ +#define CS_CFG_MATCH_CLASS_CTI_CPU 0x0008 +#define CS_CFG_MATCH_CLASS_CTI_SYS 0x0010 + +/* flags defining device instance matching - used in config data. */ +#define CS_CFG_MATCH_INST_ANY 0x80000000 /* any instance of a class */ +#define CS_CFG_MATCH_INST_AMBA_DEVICE 0x40000000 /* specific amba device */ + +/* + * 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. + * + * Supports full 64 bit register value, or 32 bit value with optional mask + * value. + * + * @flags: define value usage as 32bit, 32bit+mask or 64bit. + * @val64: 64 bit value. + * @val32: 32 bit value. + * @mask32: 32 bit mask when using 32 bit value to access device register. + */ +struct cscfg_regval { + u32 flags; + union { + u64 val64; + struct { + u32 val32; + u32 mask32; + }; + }; +}; + + +/** + * Device feature descriptor - combination of registers and parameters to + * program a device to implement a specific complex function. + * + * @name: feature name. + * @brief: brief description of the feature. + * @item: List entry. + * @match_flags: matching information if loading into a device + * @nr_params: number of parameters used. + * @params: array of parameters used. + * @nr_regs: number of registers used. + * @reg: array of registers used. + */ +struct cscfg_feature_desc { + const char *name; + const char *brief; + struct list_head item; + u32 match_flags; + int nr_params; + struct cscfg_parameter_desc *params; + int nr_regs; + struct cscfg_regval *regs; +}; + +/** + * Device / feature matching information. + * + * Used by loading configurations to define which class or specific devices + * they want to match used features to, and registered devices to specify which + * matching class and information they support. + * The load process uses these matching pairs to load feature instances into + * matching devices. + * + * @match_flags: used to match to a particular class of device. + * @dev_name: used to match to a particular device instance on the system. + * + */ +struct cscfg_match_info { + u32 match_flags; + /* unique device name (e.g. amba bus name) for specific device match */ + const char *dev_name; +}; + +/** + * Descriptor for features referenced by a configuration. + * + * @name: name of feature to use. Match against the @name in struct + * cscfg_feature_desc. + * @nr_params: number of parameters the feature has. + * @match: match info for the feature when used in this configuration - + * may be all devices of a class or a specific device in that class. + */ +struct cscfg_config_feat_ref { + const char *name; + int nr_params; + struct cscfg_match_info match; +}; + +/** + * Configuration descriptor - describes selectable system configuration. + * + * A configuration describes device features in use, and may provide preset + * values for the parameters in those features. + * + * A single set of presets is the sum of the parameters declared by + * all the features in use - this value is @nr_total_params. + * + * @name: name of the configuration - used for selection. + * @brief: description of the purpose of the configuration. + * @item: list entry. + * @nr_refs: Number of features used in this configuration. + * @refs: references to features used in this configuration.. + * @nr_presets: Number of sets of presets supplied by this configuration. + * @nr_total_params: Sum of all parameters declared by used features + * @presets: Array of preset values. + * + */ +struct cscfg_config_desc { + const char *name; + const char *brief; + struct list_head item; + int nr_refs; + struct cscfg_config_feat_ref *refs; + int nr_presets; + int nr_total_params; + const u64 *presets; /* nr_presets * nr_total_params */ +}; + +#endif /* _CORESIGHT_CORESIGHT_CONFIG_H */ diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c index 29c83eac3106..481d2b7b6b6f 100644 --- a/drivers/hwtracing/coresight/coresight-core.c +++ b/drivers/hwtracing/coresight/coresight-core.c @@ -21,6 +21,7 @@ #include "coresight-etm-perf.h" #include "coresight-priv.h" +#include "coresight-syscfg.h" static DEFINE_MUTEX(coresight_mutex); @@ -1675,13 +1676,22 @@ static int __init coresight_init(void) ret = etm_perf_init(); if (ret) - bus_unregister(&coresight_bustype); + goto exit_bus_unregister; + /* initialise the coresight syscfg API */ + ret = cscfg_init(); + if (!ret) + return 0; + + etm_perf_exit(); +exit_bus_unregister: + bus_unregister(&coresight_bustype); return ret; } static void __exit coresight_exit(void) { + cscfg_exit(); etm_perf_exit(); bus_unregister(&coresight_bustype); } diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c index bdc34ca449f7..a608081bd446 100644 --- a/drivers/hwtracing/coresight/coresight-etm-perf.c +++ b/drivers/hwtracing/coresight/coresight-etm-perf.c @@ -627,7 +627,7 @@ int __init etm_perf_init(void) return ret; } -void __exit etm_perf_exit(void) +void etm_perf_exit(void) { perf_pmu_unregister(&etm_pmu); } diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.h b/drivers/hwtracing/coresight/coresight-etm-perf.h index 3e4f2ad5e193..29d90dfeba31 100644 --- a/drivers/hwtracing/coresight/coresight-etm-perf.h +++ b/drivers/hwtracing/coresight/coresight-etm-perf.h @@ -83,6 +83,6 @@ static inline void *etm_perf_sink_config(struct perf_output_handle *handle) #endif /* CONFIG_CORESIGHT */ int __init etm_perf_init(void); -void __exit etm_perf_exit(void); +void etm_perf_exit(void); #endif diff --git a/drivers/hwtracing/coresight/coresight-syscfg.c b/drivers/hwtracing/coresight/coresight-syscfg.c new file mode 100644 index 000000000000..6f89541af7a0 --- /dev/null +++ b/drivers/hwtracing/coresight/coresight-syscfg.c @@ -0,0 +1,247 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 Linaro Limited, All rights reserved. + * Author: Mike Leach <mike.leach@linaro.org> + */ + +#include <linux/platform_device.h> + +#include "coresight-config.h" +#include "coresight-syscfg.h" + +/* + * cscfg_ API manages configurations and features for the entire coresight + * infrastructure. + * + * It allows the loading of configurations and features, and loads these into + * coresight devices as appropriate. + */ + +static DEFINE_MUTEX(cscfg_mutex); + +/* only one of these */ +static struct cscfg_api_data cscfg_data; + +/* get reference to cscfg device */ +struct device *to_device_cscfg(void); + +/* load features and configuations into the lists */ + +/* check feature list for a named feature - call with mutex locked. */ +static bool cscfg_match_list_feat(const char *name) +{ + struct cscfg_feature_desc *curr_item; + + list_for_each_entry(curr_item, &cscfg_data.feat_list, item) { + if (strcmp(curr_item->name, name) == 0) + return true; + } + return false; +} + +/* check all feat needed for cfg are in the list - call with mutex locked. */ +static int cscfg_check_feat_for_cfg(struct cscfg_config_desc *cfg_desc) +{ + int i; + + for (i = 0; i < cfg_desc->nr_refs; i++) + if (!cscfg_match_list_feat(cfg_desc->refs[i].name)) + return -EINVAL; + return 0; +} + +/* + * load feature - add to feature list. + */ +static int cscfg_load_feat(struct cscfg_feature_desc *feat_desc) +{ + list_add(&feat_desc->item, &cscfg_data.feat_list); + + return 0; +} + +/* + * load config into the system - validate used features exist then add to + * config list. + */ +static int cscfg_load_config(struct cscfg_config_desc *cfg_desc) +{ + int err; + + /* validate features are present */ + err = cscfg_check_feat_for_cfg(cfg_desc); + if (err) + return err; + + list_add(&cfg_desc->item, &cscfg_data.config_list); + + return 0; +} + +/* + * External API function to load feature and config sets. + * Take a 0 terminated array of feature descriptors and/or configuration + * descriptors and load into the system. + * Features are loaded first to ensure configuration dependencies can be met. + */ +int cscfg_load_config_sets(struct cscfg_config_desc **cfg_descs, + struct cscfg_feature_desc **feat_descs) +{ + int err, i = 0; + + mutex_lock(&cscfg_mutex); + + /* load features first */ + if (feat_descs) { + while (feat_descs[i]) { + err = cscfg_load_feat(feat_descs[i]); + if (err) { + pr_err("coresight-syscfg: Failed to load feature %s\n", + feat_descs[i]->name); + goto do_unlock; + } + i++; + } + } + + /* next any configurations to check feature dependencies */ + i = 0; + if (cfg_descs) { + while (cfg_descs[i]) { + err = cscfg_load_config(cfg_descs[i]); + if (err) { + pr_err("coresight-syscfg: Failed to load configuration %s\n", + cfg_descs[i]->name); + goto do_unlock; + } + i++; + } + } + +do_unlock: + mutex_unlock(&cscfg_mutex); + return err; +} +EXPORT_SYMBOL_GPL(cscfg_load_config_sets); + +/* Initialise system configuration management driver. */ +/* only one of these */ +static struct cscfg_device *cscfg_dev; + +/* + * We have a separate coresight-config bus for the config device so it does + * not appear on the main coresight bus and affect device searches on that bus. + */ +static struct bus_type cscfg_bus_type = { + .name = "coresight-config", +}; + +struct device *to_device_cscfg(void) +{ + return cscfg_dev ? &cscfg_dev->dev : NULL; +} + +/* Must have a release function or the kernel will complain on module unload */ +void cscfg_dev_release(struct device *dev) +{ + kfree(cscfg_dev); + cscfg_dev = NULL; +} + +int cscfg_create_device(void) +{ + struct device *dev; + int err = -ENOMEM; + + mutex_lock(&cscfg_mutex); + if (cscfg_dev) { + err = -EINVAL; + goto create_dev_exit_unlock; + } + + cscfg_dev = kzalloc(sizeof(struct cscfg_device), GFP_KERNEL); + if (!cscfg_dev) + goto create_dev_exit_unlock; + + /* setup the device */ + dev = to_device_cscfg(); + dev->bus = &cscfg_bus_type; + dev->parent = &platform_bus; + dev->release = cscfg_dev_release; + dev->init_name = "system_cfg"; + cscfg_dev->cfg_data = &cscfg_data; + + err = device_register(dev); + if (err) + cscfg_dev_release(dev); + +create_dev_exit_unlock: + mutex_unlock(&cscfg_mutex); + return err; +} + +void cscfg_clear_device(void) +{ + mutex_lock(&cscfg_mutex); + device_unregister(to_device_cscfg()); + mutex_unlock(&cscfg_mutex); +} + +/* driver initialisation */ +static struct cscfg_driver cs_config_driver = { + .drv = { + .name = "cs-syscfg-drv", + .owner = THIS_MODULE, + .suppress_bind_attrs = true, + }, +}; + +int __init cscfg_driver_init(void) +{ + cs_config_driver.drv.bus = &cscfg_bus_type; + return driver_register(&cs_config_driver.drv); +} + +void cscfg_driver_exit(void) +{ + driver_unregister(&cs_config_driver.drv); +} + +/* Initialise system config management API */ +int __init cscfg_init(void) +{ + int err = 0; + + err = bus_register(&cscfg_bus_type); + if (err) + return err; + + err = cscfg_driver_init(); + if (err) + goto exit_bus_unregister; + + err = cscfg_create_device(); + if (err) + goto exit_drv_unregister; + + INIT_LIST_HEAD(&cscfg_data.dev_list); + INIT_LIST_HEAD(&cscfg_data.feat_list); + INIT_LIST_HEAD(&cscfg_data.config_list); + cscfg_data.nr_csdev = 0; + + dev_info(to_device_cscfg(), "CoreSight Configuration manager initialised"); + return 0; + +exit_drv_unregister: + cscfg_driver_exit(); +exit_bus_unregister: + bus_unregister(&cscfg_bus_type); + return err; +} + +void __exit cscfg_exit(void) +{ + cscfg_clear_device(); + cscfg_driver_exit(); + bus_unregister(&cscfg_bus_type); +} diff --git a/drivers/hwtracing/coresight/coresight-syscfg.h b/drivers/hwtracing/coresight/coresight-syscfg.h new file mode 100644 index 000000000000..5a7896426eab --- /dev/null +++ b/drivers/hwtracing/coresight/coresight-syscfg.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Coresight system configuration driver. + */ + +#ifndef CORESIGHT_SYSCFG_H +#define CORESIGHT_SYSCFG_H + +#include <linux/coresight.h> +#include <linux/device.h> + +#include "coresight-config.h" + +/** + * System configuration API data. + * + * @dev_list: List of other coresight devices registered with this device. + * @feat_list: List of features to load into registered devices. + * @config_list:List of system configurations to load into registered devices. + * @nr_csdev: Number of registered devices with the cscfg system + */ +struct cscfg_api_data { + struct list_head dev_list; + struct list_head feat_list; + struct list_head config_list; + int nr_csdev; +}; + +/* internal core operations for cscfg */ +int __init cscfg_init(void); +void __exit cscfg_exit(void); + +/* syscfg external API */ +int cscfg_load_config_sets(struct cscfg_config_desc **cfg_descs, + struct cscfg_feature_desc **feat_descs); + +/* system configuration device driver and API */ +/** + * System configuration device. + * + * Need a device to 'own' some coresight system wide sysfs entries in + * perf events etc. + * + * @dev: The device. + * @cfg_data: A reference to the configuration and feature lists + */ +struct cscfg_device { + struct device dev; + struct cscfg_api_data *cfg_data; +}; + +/* basic device driver */ +struct cscfg_driver { + struct device_driver drv; +}; + +#endif /* CORESIGHT_SYSCFG_H */
Creates an system management API to allow complex configurations and features to be programmed into a CoreSight infrastructure. A feature is defined as a programming set for a device or class of devices. A configuration is a set of features across the system that are enabled for a trace session. The API will manage system wide configuration, and allow complex programmed features to be added to individual device instances, and provide for system wide configuration selection on trace capture operations. This patch creates the initial data object and the initial API for loading configurations and features. Signed-off-by: Mike Leach <mike.leach@linaro.org> --- drivers/hwtracing/coresight/Makefile | 2 +- .../hwtracing/coresight/coresight-config.h | 170 ++++++++++++ drivers/hwtracing/coresight/coresight-core.c | 12 +- .../hwtracing/coresight/coresight-etm-perf.c | 2 +- .../hwtracing/coresight/coresight-etm-perf.h | 2 +- .../hwtracing/coresight/coresight-syscfg.c | 247 ++++++++++++++++++ .../hwtracing/coresight/coresight-syscfg.h | 57 ++++ 7 files changed, 488 insertions(+), 4 deletions(-) create mode 100644 drivers/hwtracing/coresight/coresight-config.h create mode 100644 drivers/hwtracing/coresight/coresight-syscfg.c create mode 100644 drivers/hwtracing/coresight/coresight-syscfg.h