From: Mike Leach <hidden> Date: 2021-01-28 17:50:23
This patchset introduces initial concepts in CoreSight system
configuration management support. to allow more detailed and complex
programming to be applied to CoreSight systems during trace capture.
Configurations consist of 2 elements:-
1) Features - programming combinations for devices, applied to a class of
device on the system (all ETMv4), or individual devices.
2) Configurations - a set of programmed features used when the named
configuration is selected.
Features and configurations are declared as a data table, a set of register,
resource and parameter requirements. Features and configurations are loaded
into the system by the virtual cs_syscfg device. This then matches features
to any registered devices and loads the feature into them.
Individual device classes that support feature and configuration register
with cs_syscfg.
Once loaded a configuration can be enabled for a specific trace run.
Configurations are registered with the perf cs_etm event as entries in
cs_etm/cs_config. These can be selected on the perf command line as follows:-
perf record -e cs_etm/<config_name>/ ...
This patch set has one pre-loaded configuration and feature.
A named "strobing" feature is provided for ETMv4.
A named "autofdo" configuration is provided. This configuration enables
strobing on any ETM in used.
Thus the command:
perf record -e cs_etm/autofdo/ ...
will trace the supplied application while enabling the "autofdo" configuation
on each ETM as it is enabled by perf. This in turn will enable strobing for
the ETM - with default parameters. Parameters can be adjusted using configfs.
The sink used in the trace run will be automatically selected.
A configuation can supply up to 15 of preset parameter values, which will
subsitute in parameter values for any feature used in the configuration.
Selection of preset values as follows
perf record -e cs_etm/autofdo,preset=1/ ...
(valid presets 1-N, where N is the number supplied in the configuration, not
exceeding 15. preset=0 is the same as not selecting a preset.)
Applies to coresight/next (5.11-rc2 base)
Changes since v3: (Primarily based on comments from Matthieu)
1) Locking mechanisms simplified.
2) Removed the possibility to enable features independently from
configurations.Only configurations can be enabled now. Simplifies programming
logic.
3) Configuration now uses an activate->enable mechanism. This means that perf
will activate a selected configuration at the start of a session (during
setup_aux), and disable at the end of a session (around free_aux)
The active configuration and associated features will be programmed into the
CoreSight device instances when they are enabled. This locks the configuration
into the system while in use. Parameters cannot be altered while this is
in place. This mechanism will be extended in future for dynamic load / unload
of configurations to prevent removal while in use.
4) Removed the custom bus / driver as un-necessary. A single device is
registered to own perf fs elements and configfs.
5) Various other minor issues addressed.
Changes since v2:
1) Added documentation file.
2) Altered cs_syscfg driver to no longer be coresight_device based, and moved
to its own custom bus to remove it from the main coresight bus. (Mathieu)
3) Added configfs support to inspect and control loaded configurations and
features. Allows listing of preset values (Yabin Cui)
4) Dropped sysfs support for adjusting feature parameters on the per device
basis, in favour of a single point adjustment in configfs that is pushed to all
device instances.
5) Altered how the config and preset command line options are handled in perf
and the drivers. (Mathieu and Suzuki).
6) Fixes for various issues and technical points (Mathieu, Yabin)
Changes since v1:
1) Moved preloaded configurations and features out of individual drivers.
2) Added cs_syscfg driver to manage configurations and features. Individual
drivers register with cs_syscfg indicating support for config, and provide
matching information that the system uses to load features into the drivers.
This allows individual drivers to be updated on an as needed basis - and
removes the need to consider devices that cannot benefit from configuration -
static replicators, funnels, tpiu.
3) Added perf selection of configuarations.
4) Rebased onto the coresight module loading set.
To follow in future revisions / sets:-
a) load of additional config and features by loadable module.
b) load of additional config and features by configfs
c) enhanced resource management for ETMv4 and checking features have sufficient
resources to be enabled.
d) ECT and CTI support for configuration and features.
Mike Leach (10):
coresight: syscfg: Initial coresight system configuration
coresight: syscfg: Add registration and feature loading for cs devices
coresight: config: Add configuration and feature generic functions
coresight: etm-perf: update to handle configuration selection
coresight: syscfg: Add API to activate and enable configurations
coresight: etm-perf: Update to activate selected configuration
coresight: etm4x: Add complex configuration handlers to etmv4
coresight: config: Add preloaded configurations
coresight: syscfg: Add initial configfs support
coresight: docs: Add documentation for CoreSight config
.../trace/coresight/coresight-config.rst | 244 ++++++
Documentation/trace/coresight/coresight.rst | 16 +
drivers/hwtracing/coresight/Makefile | 7 +-
.../hwtracing/coresight/coresight-cfg-afdo.c | 154 ++++
.../coresight/coresight-cfg-preload.c | 25 +
.../coresight/coresight-cfg-preload.h | 11 +
.../hwtracing/coresight/coresight-config.c | 246 ++++++
.../hwtracing/coresight/coresight-config.h | 282 +++++++
drivers/hwtracing/coresight/coresight-core.c | 18 +-
.../hwtracing/coresight/coresight-etm-perf.c | 180 ++++-
.../hwtracing/coresight/coresight-etm-perf.h | 12 +-
.../hwtracing/coresight/coresight-etm4x-cfg.c | 184 +++++
.../hwtracing/coresight/coresight-etm4x-cfg.h | 29 +
.../coresight/coresight-etm4x-core.c | 38 +-
.../coresight/coresight-etm4x-sysfs.c | 3 +
.../coresight/coresight-syscfg-configfs.c | 399 +++++++++
.../coresight/coresight-syscfg-configfs.h | 45 ++
.../hwtracing/coresight/coresight-syscfg.c | 761 ++++++++++++++++++
.../hwtracing/coresight/coresight-syscfg.h | 90 +++
include/linux/coresight.h | 7 +
20 files changed, 2721 insertions(+), 30 deletions(-)
create mode 100644 Documentation/trace/coresight/coresight-config.rst
create mode 100644 drivers/hwtracing/coresight/coresight-cfg-afdo.c
create mode 100644 drivers/hwtracing/coresight/coresight-cfg-preload.c
create mode 100644 drivers/hwtracing/coresight/coresight-cfg-preload.h
create mode 100644 drivers/hwtracing/coresight/coresight-config.c
create mode 100644 drivers/hwtracing/coresight/coresight-config.h
create mode 100644 drivers/hwtracing/coresight/coresight-etm4x-cfg.c
create mode 100644 drivers/hwtracing/coresight/coresight-etm4x-cfg.h
create mode 100644 drivers/hwtracing/coresight/coresight-syscfg-configfs.c
create mode 100644 drivers/hwtracing/coresight/coresight-syscfg-configfs.h
create mode 100644 drivers/hwtracing/coresight/coresight-syscfg.c
create mode 100644 drivers/hwtracing/coresight/coresight-syscfg.h
--
2.17.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
From: Mike Leach <hidden> Date: 2021-01-28 17:12:58
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 <redacted>
---
drivers/hwtracing/coresight/Makefile | 2 +-
.../hwtracing/coresight/coresight-config.h | 167 +++++++++++++++
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 | 197 ++++++++++++++++++
.../hwtracing/coresight/coresight-syscfg.h | 54 +++++
7 files changed, 432 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
@@ -0,0 +1,167 @@+/* SPDX-License-Identifier: GPL-2.0 */+/*+*Copyright(c)2020LinaroLimited,Allrightsreserved.+*Author:MikeLeach<mike.leach@linaro.org>+*/++#ifndef _CORESIGHT_CORESIGHT_CONFIG_H+#define _CORESIGHT_CORESIGHT_CONFIG_H++#include<linux/coresight.h>+#include<linux/types.h>++/* CoreSight Configuration Management - component and system wide configuration */++/*+*Registertypeflagsforregistervaluedescriptor:+*describehowthevalueisinterpreted,andhandled.+*/+#define CS_CFG_REG_TYPE_STD 0x80 /* reg is standard reg */+#define CS_CFG_REG_TYPE_RESOURCE 0x40 /* reg is a resource */+#define CS_CFG_REG_TYPE_VAL_PARAM 0x08 /* reg value uses param */+#define CS_CFG_REG_TYPE_VAL_MASK 0x04 /* reg value bit masked */+#define CS_CFG_REG_TYPE_VAL_64BIT 0x02 /* reg value 64 bit */+#define CS_CFG_REG_TYPE_VAL_SAVE 0x01 /* reg value save on disable */++/*+*flagsdefiningwhatdeviceclassafeaturewillmatchtowhenprocessinga+*systemconfiguration-usedbyconfigdataanddevices.+*/+#define CS_CFG_MATCH_CLASS_SRC_ALL 0x0001 /* match any source */+#define CS_CFG_MATCH_CLASS_SRC_ETM4 0x0002 /* match any ETMv4 device */++/* flags defining device instance matching - used in config match desc data. */+#define CS_CFG_MATCH_INST_ANY 0x80000000 /* any instance of a class */++/*+*Limitnumberofpresetsinaconfiguration+*Thisisrelatedtothenumberofbits(4)weusetoselectthepreseton+*theperfcommandline.Preset0isalwaysnoneselected.+*SeePMU_FORMAT_ATTR(preset,"config:0-3")incoresight-etm-perf.c+*/+#define CS_CFG_CONFIG_PRESET_MAX 15++/**+*Parameterdescriptorforadevicefeature.+*+*@name:Nameofparameter.+*@value:Initialordefaultvalue.+*/+structcscfg_parameter_desc{+constchar*name;+u64value;+};++/**+*Representationofregistervalue.+*+*Supportsfull64bitregistervalue,or32bitvaluewithoptionalmask+*value.+*+*@type:defineregisterusageandinterpretation.+*@offset:theaddressoffsetforregisterinthehardwaredevice(perdevicespecification).+*@hw_info:optionalhardwaredevicetypespecificinformation.(ETM/CTIspecificetc)+*@val64:64bitvalue.+*@val32:32bitvalue.+*@mask32:32bitmaskwhenusing32bitvaluetoaccessdeviceregister.+*/+structcscfg_regval_desc{+struct{+u32type:8;+u32offset:12;+u32hw_info:12;+};+union{+u64val64;+struct{+u32val32;+u32mask32;+};+};+};++/**+*Devicefeaturedescriptor-combinationofregistersandparametersto+*programadevicetoimplementaspecificcomplexfunction.+*+*@name:featurename.+*@brief:briefdescriptionofthefeature.+*@item:Listentry.+*@match_flags:matchinginformationifloadingintoadevice+*@nr_params:numberofparametersused.+*@params:arrayofparametersused.+*@nr_regs:numberofregistersused.+*@reg:arrayofregistersused.+*/+structcscfg_feature_desc{+constchar*name;+constchar*brief;+structlist_headitem;+u32match_flags;+intnr_params;+structcscfg_parameter_desc*params;+intnr_regs;+structcscfg_regval_desc*regs;+};++/**+*Matchdescriptor-Device/featurematchingwhenloadingintodevices+*+*Usedbyloadingconfigurationstodefinewhichclassorspecificdevices+*theywanttomatchusedfeaturesto,andregistereddevicestospecifywhich+*matchingclassandinformationtheysupport.+*+*Theloadprocessusesthesematchingpairstoloadfeatureinstancesinto+*matchingdevices.+*+*@match_flags:usedtomatchtoaparticularclassofdevice.+*+*/+structcscfg_match_desc{+u32match_flags;+};++/**+*Descriptorforfeaturesreferencedbyaconfiguration.+*+*@name:nameoffeaturetouse.Matchagainstthe@nameinstruct+*cscfg_feature_desc.+*@match:matchinfoforthefeaturewhenusedinthisconfiguration-+*maybealldevicesofaclassoraspecificdeviceinthatclass.+*/+structcscfg_config_feat_ref{+constchar*name;+structcscfg_match_descmatch;+};++/**+*Configurationdescriptor-describesselectablesystemconfiguration.+*+*Aconfigurationdescribesdevicefeaturesinuse,andmayprovidepreset+*valuesfortheparametersinthosefeatures.+*+*Asinglesetofpresetsisthesumoftheparametersdeclaredby+*allthefeaturesinuse-thisvalueis@nr_total_params.+*+*@name:nameoftheconfiguration-usedforselection.+*@brief:descriptionofthepurposeoftheconfiguration.+*@item:listentry.+*@nr_refs:Numberoffeaturesusedinthisconfiguration.+*@refs:referencestofeaturesusedinthisconfiguration..+*@nr_presets:Numberofsetsofpresetssuppliedbythisconfiguration.+*@nr_total_params:Sumofallparametersdeclaredbyusedfeatures+*@presets:Arrayofpresetvalues.+*+*/+structcscfg_config_desc{+constchar*name;+constchar*brief;+structlist_headitem;+intnr_refs;+structcscfg_config_feat_ref*refs;+intnr_presets;+intnr_total_params;+constu64*presets;/* nr_presets * nr_total_params */+};++#endif /* _CORESIGHT_CORESIGHT_CONFIG_H */
@@ -1739,13 +1740,22 @@ static int __init coresight_init(void)ret=etm_perf_init();if(ret)-bus_unregister(&coresight_bustype);+gotoexit_bus_unregister;+/* initialise the coresight syscfg API */+ret=cscfg_init();+if(!ret)+return0;++etm_perf_exit();+exit_bus_unregister:+bus_unregister(&coresight_bustype);returnret;}staticvoid__exitcoresight_exit(void){+cscfg_exit();etm_perf_exit();bus_unregister(&coresight_bustype);}
@@ -0,0 +1,197 @@+// SPDX-License-Identifier: GPL-2.0+/*+*Copyright(c)2020LinaroLimited,Allrightsreserved.+*Author:MikeLeach<mike.leach@linaro.org>+*/++#include<linux/platform_device.h>++#include"coresight-config.h"+#include"coresight-syscfg.h"++/*+*cscfg_APImanagesconfigurationsandfeaturesfortheentirecoresight+*infrastructure.+*+*Itallowstheloadingofconfigurationsandfeatures,andloadstheseinto+*coresightdevicesasappropriate.+*/++/* protect the cscsg_data and device */+staticDEFINE_MUTEX(cscfg_mutex);++/* only one of these */+staticstructcscfg_manager*cscfg_mgr;++/* load features and configuations into the lists */++/* check feature list for a named feature - call with mutex locked. */+staticboolcscfg_match_list_feat(constchar*name)+{+structcscfg_feature_desc*curr_item;++list_for_each_entry(curr_item,&cscfg_mgr->data.feat_desc_list,item){+if(strcmp(curr_item->name,name)==0)+returntrue;+}+returnfalse;+}++/* check all feat needed for cfg are in the list - call with mutex locked. */+staticintcscfg_check_feat_for_cfg(structcscfg_config_desc*cfg_desc)+{+inti;++for(i=0;i<cfg_desc->nr_refs;i++)+if(!cscfg_match_list_feat(cfg_desc->refs[i].name))+return-EINVAL;+return0;+}++/*+*loadfeature-addtofeaturelist.+*/+staticintcscfg_load_feat(structcscfg_feature_desc*feat_desc)+{+list_add(&feat_desc->item,&cscfg_mgr->data.feat_desc_list);++return0;+}++/*+*loadconfigintothesystem-validateusedfeaturesexistthenaddto+*configlist.+*/+staticintcscfg_load_config(structcscfg_config_desc*cfg_desc)+{+interr;++/* validate features are present */+err=cscfg_check_feat_for_cfg(cfg_desc);+if(err)+returnerr;++list_add(&cfg_desc->item,&cscfg_mgr->data.config_desc_list);++return0;+}++/*+*ExternalAPIfunctiontoloadfeatureandconfigsets.+*Takea0terminatedarrayoffeaturedescriptorsand/orconfiguration+*descriptorsandloadintothesystem.+*Featuresareloadedfirsttoensureconfigurationdependenciescanbemet.+*/+intcscfg_load_config_sets(structcscfg_config_desc**cfg_descs,+structcscfg_feature_desc**feat_descs)+{+interr,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);+gotodo_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);+gotodo_unlock;+}+i++;+}+}++do_unlock:+mutex_unlock(&cscfg_mutex);+returnerr;+}+EXPORT_SYMBOL_GPL(cscfg_load_config_sets);++/* Initialise system configuration management device. */++structdevice*to_device_cscfg(void)+{+returncscfg_mgr?&cscfg_mgr->dev:NULL;+}++/* Must have a release function or the kernel will complain on module unload */+voidcscfg_dev_release(structdevice*dev)+{+kfree(cscfg_mgr);+cscfg_mgr=NULL;+}++/* a device is needed to "own" some kernel elements such as sysfs entries. */+intcscfg_create_device(void)+{+structdevice*dev;+interr=-ENOMEM;++mutex_lock(&cscfg_mutex);+if(cscfg_mgr){+err=-EINVAL;+gotocreate_dev_exit_unlock;+}++cscfg_mgr=kzalloc(sizeof(structcscfg_manager),GFP_KERNEL);+if(!cscfg_mgr)+gotocreate_dev_exit_unlock;++/* setup the device */+dev=to_device_cscfg();+dev->release=cscfg_dev_release;+dev->init_name="system_cfg";++err=device_register(dev);+if(err)+cscfg_dev_release(dev);++create_dev_exit_unlock:+mutex_unlock(&cscfg_mutex);+returnerr;+}++voidcscfg_clear_device(void)+{+mutex_lock(&cscfg_mutex);+device_unregister(to_device_cscfg());+mutex_unlock(&cscfg_mutex);+}++/* Initialise system config management API device */+int__initcscfg_init(void)+{+interr=0;++err=cscfg_create_device();+if(err)+returnerr;++INIT_LIST_HEAD(&cscfg_mgr->data.csdev_desc_list);+INIT_LIST_HEAD(&cscfg_mgr->data.feat_desc_list);+INIT_LIST_HEAD(&cscfg_mgr->data.config_desc_list);+cscfg_mgr->data.nr_csdev=0;++dev_info(to_device_cscfg(),"CoreSight Configuration manager initialised");+return0;+}++void__exitcscfg_exit(void)+{+cscfg_clear_device();+}
@@ -0,0 +1,54 @@+/* SPDX-License-Identifier: GPL-2.0-only */+/*+*Coresightsystemconfigurationdriver.+*/++#ifndef CORESIGHT_SYSCFG_H+#define CORESIGHT_SYSCFG_H++#include<linux/coresight.h>+#include<linux/device.h>++#include"coresight-config.h"++/**+*SystemconfigurationmanagerAPIdata.+*+*@csdev_list:Listofcoresightdevicesregisteredwiththeconfigurationmanager.+*@feat_desc_list:Listoffeaturedescriptorstoloadintoregistereddevices.+*@config_desc_list:Listofsystemconfigurationdescriptorstoloadintoregistereddevices.+*@nr_csdev:Numberofregistereddeviceswiththecscfgsystem+*/+structcscfg_api_data{+structlist_headcsdev_desc_list;+structlist_headfeat_desc_list;+structlist_headconfig_desc_list;+intnr_csdev;+};++/* internal core operations for cscfg */+int__initcscfg_init(void);+void__exitcscfg_exit(void);++/* syscfg manager external API */+intcscfg_load_config_sets(structcscfg_config_desc**cfg_descs,+structcscfg_feature_desc**feat_descs);++/**+*Systemconfigurationmanagerdevice.+*+*Needadeviceto'own'somecoresightsystemwidesysfsentriesin+*perfevents,configfsetc.+*+*@dev:Thedevice.+*@data:TheAPIdata.+*/+structcscfg_manager{+structdevicedev;+structcscfg_api_datadata;+};++/* get reference to dev in cscfg_manager */+structdevice*to_device_cscfg(void);++#endif /* CORESIGHT_SYSCFG_H */
--
2.17.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
On Thu, Jan 28, 2021 at 05:09:27PM +0000, Mike Leach wrote:
quoted hunk
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 <redacted>
---
drivers/hwtracing/coresight/Makefile | 2 +-
.../hwtracing/coresight/coresight-config.h | 167 +++++++++++++++
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 | 197 ++++++++++++++++++
.../hwtracing/coresight/coresight-syscfg.h | 54 +++++
7 files changed, 432 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
@@ -0,0 +1,167 @@+/* SPDX-License-Identifier: GPL-2.0 */+/*+*Copyright(c)2020LinaroLimited,Allrightsreserved.+*Author:MikeLeach<mike.leach@linaro.org>+*/++#ifndef _CORESIGHT_CORESIGHT_CONFIG_H+#define _CORESIGHT_CORESIGHT_CONFIG_H++#include<linux/coresight.h>+#include<linux/types.h>++/* CoreSight Configuration Management - component and system wide configuration */++/*+*Registertypeflagsforregistervaluedescriptor:+*describehowthevalueisinterpreted,andhandled.+*/+#define CS_CFG_REG_TYPE_STD 0x80 /* reg is standard reg */+#define CS_CFG_REG_TYPE_RESOURCE 0x40 /* reg is a resource */+#define CS_CFG_REG_TYPE_VAL_PARAM 0x08 /* reg value uses param */+#define CS_CFG_REG_TYPE_VAL_MASK 0x04 /* reg value bit masked */+#define CS_CFG_REG_TYPE_VAL_64BIT 0x02 /* reg value 64 bit */+#define CS_CFG_REG_TYPE_VAL_SAVE 0x01 /* reg value save on disable */++/*+*flagsdefiningwhatdeviceclassafeaturewillmatchtowhenprocessinga+*systemconfiguration-usedbyconfigdataanddevices.+*/+#define CS_CFG_MATCH_CLASS_SRC_ALL 0x0001 /* match any source */+#define CS_CFG_MATCH_CLASS_SRC_ETM4 0x0002 /* match any ETMv4 device */++/* flags defining device instance matching - used in config match desc data. */+#define CS_CFG_MATCH_INST_ANY 0x80000000 /* any instance of a class */++/*+*Limitnumberofpresetsinaconfiguration+*Thisisrelatedtothenumberofbits(4)weusetoselectthepreseton+*theperfcommandline.Preset0isalwaysnoneselected.+*SeePMU_FORMAT_ATTR(preset,"config:0-3")incoresight-etm-perf.c+*/+#define CS_CFG_CONFIG_PRESET_MAX 15++/**+*Parameterdescriptorforadevicefeature.+*+*@name:Nameofparameter.+*@value:Initialordefaultvalue.+*/+structcscfg_parameter_desc{+constchar*name;+u64value;+};++/**+*Representationofregistervalue.+*+*Supportsfull64bitregistervalue,or32bitvaluewithoptionalmask+*value.+*+*@type:defineregisterusageandinterpretation.+*@offset:theaddressoffsetforregisterinthehardwaredevice(perdevicespecification).+*@hw_info:optionalhardwaredevicetypespecificinformation.(ETM/CTIspecificetc)+*@val64:64bitvalue.+*@val32:32bitvalue.+*@mask32:32bitmaskwhenusing32bitvaluetoaccessdeviceregister.+*/+structcscfg_regval_desc{+struct{+u32type:8;+u32offset:12;+u32hw_info:12;+};+union{+u64val64;+struct{+u32val32;+u32mask32;+};+};+};++/**+*Devicefeaturedescriptor-combinationofregistersandparametersto+*programadevicetoimplementaspecificcomplexfunction.+*+*@name:featurename.+*@brief:briefdescriptionofthefeature.+*@item:Listentry.+*@match_flags:matchinginformationifloadingintoadevice+*@nr_params:numberofparametersused.+*@params:arrayofparametersused.+*@nr_regs:numberofregistersused.+*@reg:arrayofregistersused.+*/+structcscfg_feature_desc{+constchar*name;+constchar*brief;+structlist_headitem;+u32match_flags;+intnr_params;+structcscfg_parameter_desc*params;+intnr_regs;+structcscfg_regval_desc*regs;+};++/**+*Matchdescriptor-Device/featurematchingwhenloadingintodevices+*+*Usedbyloadingconfigurationstodefinewhichclassorspecificdevices+*theywanttomatchusedfeaturesto,andregistereddevicestospecifywhich+*matchingclassandinformationtheysupport.+*+*Theloadprocessusesthesematchingpairstoloadfeatureinstancesinto+*matchingdevices.+*+*@match_flags:usedtomatchtoaparticularclassofdevice.+*+*/+structcscfg_match_desc{+u32match_flags;+};++/**+*Descriptorforfeaturesreferencedbyaconfiguration.+*+*@name:nameoffeaturetouse.Matchagainstthe@nameinstruct+*cscfg_feature_desc.+*@match:matchinfoforthefeaturewhenusedinthisconfiguration-+*maybealldevicesofaclassoraspecificdeviceinthatclass.+*/+structcscfg_config_feat_ref{+constchar*name;+structcscfg_match_descmatch;
I would get rid of structure cscfg_match_desc and put @match_flags right here.
How often do you envision features having different matches for different
configuration? If there is no real use for it we could use @name and
@match_flags from structure cscfg_feature_desck and get rid of
cscfg_config_feat_ref entirely.
quoted hunk
+};
+
+/**
+ * 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 */
@@ -1739,13 +1740,22 @@ static int __init coresight_init(void)ret=etm_perf_init();if(ret)-bus_unregister(&coresight_bustype);+gotoexit_bus_unregister;+/* initialise the coresight syscfg API */+ret=cscfg_init();+if(!ret)+return0;++etm_perf_exit();+exit_bus_unregister:+bus_unregister(&coresight_bustype);returnret;}staticvoid__exitcoresight_exit(void){+cscfg_exit();etm_perf_exit();bus_unregister(&coresight_bustype);}
@@ -0,0 +1,197 @@+// SPDX-License-Identifier: GPL-2.0+/*+*Copyright(c)2020LinaroLimited,Allrightsreserved.+*Author:MikeLeach<mike.leach@linaro.org>+*/++#include<linux/platform_device.h>++#include"coresight-config.h"+#include"coresight-syscfg.h"++/*+*cscfg_APImanagesconfigurationsandfeaturesfortheentirecoresight+*infrastructure.+*+*Itallowstheloadingofconfigurationsandfeatures,andloadstheseinto+*coresightdevicesasappropriate.+*/++/* protect the cscsg_data and device */+staticDEFINE_MUTEX(cscfg_mutex);++/* only one of these */+staticstructcscfg_manager*cscfg_mgr;++/* load features and configuations into the lists */++/* check feature list for a named feature - call with mutex locked. */+staticboolcscfg_match_list_feat(constchar*name)+{+structcscfg_feature_desc*curr_item;++list_for_each_entry(curr_item,&cscfg_mgr->data.feat_desc_list,item){+if(strcmp(curr_item->name,name)==0)+returntrue;+}+returnfalse;+}++/* check all feat needed for cfg are in the list - call with mutex locked. */+staticintcscfg_check_feat_for_cfg(structcscfg_config_desc*cfg_desc)+{+inti;++for(i=0;i<cfg_desc->nr_refs;i++)+if(!cscfg_match_list_feat(cfg_desc->refs[i].name))+return-EINVAL;+return0;+}++/*+*loadfeature-addtofeaturelist.+*/+staticintcscfg_load_feat(structcscfg_feature_desc*feat_desc)+{+list_add(&feat_desc->item,&cscfg_mgr->data.feat_desc_list);++return0;+}++/*+*loadconfigintothesystem-validateusedfeaturesexistthenaddto+*configlist.+*/+staticintcscfg_load_config(structcscfg_config_desc*cfg_desc)+{+interr;++/* validate features are present */+err=cscfg_check_feat_for_cfg(cfg_desc);+if(err)+returnerr;++list_add(&cfg_desc->item,&cscfg_mgr->data.config_desc_list);++return0;+}++/*+*ExternalAPIfunctiontoloadfeatureandconfigsets.+*Takea0terminatedarrayoffeaturedescriptorsand/orconfiguration+*descriptorsandloadintothesystem.+*Featuresareloadedfirsttoensureconfigurationdependenciescanbemet.+*/+intcscfg_load_config_sets(structcscfg_config_desc**cfg_descs,+structcscfg_feature_desc**feat_descs)+{+interr,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);+gotodo_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);+gotodo_unlock;+}+i++;+}+}++do_unlock:+mutex_unlock(&cscfg_mutex);+returnerr;+}+EXPORT_SYMBOL_GPL(cscfg_load_config_sets);++/* Initialise system configuration management device. */++structdevice*to_device_cscfg(void)+{+returncscfg_mgr?&cscfg_mgr->dev:NULL;+}++/* Must have a release function or the kernel will complain on module unload */+voidcscfg_dev_release(structdevice*dev)+{+kfree(cscfg_mgr);+cscfg_mgr=NULL;+}++/* a device is needed to "own" some kernel elements such as sysfs entries. */+intcscfg_create_device(void)+{+structdevice*dev;+interr=-ENOMEM;++mutex_lock(&cscfg_mutex);+if(cscfg_mgr){+err=-EINVAL;+gotocreate_dev_exit_unlock;+}++cscfg_mgr=kzalloc(sizeof(structcscfg_manager),GFP_KERNEL);+if(!cscfg_mgr)+gotocreate_dev_exit_unlock;++/* setup the device */+dev=to_device_cscfg();+dev->release=cscfg_dev_release;+dev->init_name="system_cfg";++err=device_register(dev);+if(err)+cscfg_dev_release(dev);++create_dev_exit_unlock:+mutex_unlock(&cscfg_mutex);+returnerr;+}
We are keeping track of the number of cs devices registered with the manager but
I don't see a place (in this patchset) where the information is used. If indeed
we dont' need it I suggest moving the lists held in cscfg_api_data directly to
cscfg_manager.
@@ -0,0 +1,54 @@+/* SPDX-License-Identifier: GPL-2.0-only */+/*+*Coresightsystemconfigurationdriver.+*/++#ifndef CORESIGHT_SYSCFG_H+#define CORESIGHT_SYSCFG_H++#include<linux/coresight.h>+#include<linux/device.h>++#include"coresight-config.h"++/**+*SystemconfigurationmanagerAPIdata.+*+*@csdev_list:Listofcoresightdevicesregisteredwiththeconfigurationmanager.+*@feat_desc_list:Listoffeaturedescriptorstoloadintoregistereddevices.+*@config_desc_list:Listofsystemconfigurationdescriptorstoloadintoregistereddevices.+*@nr_csdev:Numberofregistereddeviceswiththecscfgsystem+*/+structcscfg_api_data{+structlist_headcsdev_desc_list;+structlist_headfeat_desc_list;+structlist_headconfig_desc_list;+intnr_csdev;+};++/* internal core operations for cscfg */+int__initcscfg_init(void);+void__exitcscfg_exit(void);++/* syscfg manager external API */+intcscfg_load_config_sets(structcscfg_config_desc**cfg_descs,+structcscfg_feature_desc**feat_descs);++/**+*Systemconfigurationmanagerdevice.+*+*Needadeviceto'own'somecoresightsystemwidesysfsentriesin+*perfevents,configfsetc.+*+*@dev:Thedevice.+*@data:TheAPIdata.+*/+structcscfg_manager{+structdevicedev;+structcscfg_api_datadata;+};++/* get reference to dev in cscfg_manager */+structdevice*to_device_cscfg(void);
This patch looks really good now. More comments to come tomorrow.
Thanks,
Mathieu
From: Mike Leach <hidden> Date: 2021-02-26 19:11:05
Hi Mathieu,
On Thu, 18 Feb 2021 at 23:52, Mathieu Poirier
[off-list ref] wrote:
On Thu, Jan 28, 2021 at 05:09:27PM +0000, Mike Leach wrote:
quoted
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 <redacted>
---
drivers/hwtracing/coresight/Makefile | 2 +-
.../hwtracing/coresight/coresight-config.h | 167 +++++++++++++++
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 | 197 ++++++++++++++++++
.../hwtracing/coresight/coresight-syscfg.h | 54 +++++
7 files changed, 432 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
@@ -0,0 +1,167 @@+/* SPDX-License-Identifier: GPL-2.0 */+/*+*Copyright(c)2020LinaroLimited,Allrightsreserved.+*Author:MikeLeach<mike.leach@linaro.org>+*/++#ifndef _CORESIGHT_CORESIGHT_CONFIG_H+#define _CORESIGHT_CORESIGHT_CONFIG_H++#include<linux/coresight.h>+#include<linux/types.h>++/* CoreSight Configuration Management - component and system wide configuration */++/*+*Registertypeflagsforregistervaluedescriptor:+*describehowthevalueisinterpreted,andhandled.+*/+#define CS_CFG_REG_TYPE_STD 0x80 /* reg is standard reg */+#define CS_CFG_REG_TYPE_RESOURCE 0x40 /* reg is a resource */+#define CS_CFG_REG_TYPE_VAL_PARAM 0x08 /* reg value uses param */+#define CS_CFG_REG_TYPE_VAL_MASK 0x04 /* reg value bit masked */+#define CS_CFG_REG_TYPE_VAL_64BIT 0x02 /* reg value 64 bit */+#define CS_CFG_REG_TYPE_VAL_SAVE 0x01 /* reg value save on disable */++/*+*flagsdefiningwhatdeviceclassafeaturewillmatchtowhenprocessinga+*systemconfiguration-usedbyconfigdataanddevices.+*/+#define CS_CFG_MATCH_CLASS_SRC_ALL 0x0001 /* match any source */+#define CS_CFG_MATCH_CLASS_SRC_ETM4 0x0002 /* match any ETMv4 device */++/* flags defining device instance matching - used in config match desc data. */+#define CS_CFG_MATCH_INST_ANY 0x80000000 /* any instance of a class */++/*+*Limitnumberofpresetsinaconfiguration+*Thisisrelatedtothenumberofbits(4)weusetoselectthepreseton+*theperfcommandline.Preset0isalwaysnoneselected.+*SeePMU_FORMAT_ATTR(preset,"config:0-3")incoresight-etm-perf.c+*/+#define CS_CFG_CONFIG_PRESET_MAX 15++/**+*Parameterdescriptorforadevicefeature.+*+*@name:Nameofparameter.+*@value:Initialordefaultvalue.+*/+structcscfg_parameter_desc{+constchar*name;+u64value;+};++/**+*Representationofregistervalue.+*+*Supportsfull64bitregistervalue,or32bitvaluewithoptionalmask+*value.+*+*@type:defineregisterusageandinterpretation.+*@offset:theaddressoffsetforregisterinthehardwaredevice(perdevicespecification).+*@hw_info:optionalhardwaredevicetypespecificinformation.(ETM/CTIspecificetc)+*@val64:64bitvalue.+*@val32:32bitvalue.+*@mask32:32bitmaskwhenusing32bitvaluetoaccessdeviceregister.+*/+structcscfg_regval_desc{+struct{+u32type:8;+u32offset:12;+u32hw_info:12;+};+union{+u64val64;+struct{+u32val32;+u32mask32;+};+};+};++/**+*Devicefeaturedescriptor-combinationofregistersandparametersto+*programadevicetoimplementaspecificcomplexfunction.+*+*@name:featurename.+*@brief:briefdescriptionofthefeature.+*@item:Listentry.+*@match_flags:matchinginformationifloadingintoadevice+*@nr_params:numberofparametersused.+*@params:arrayofparametersused.+*@nr_regs:numberofregistersused.+*@reg:arrayofregistersused.+*/+structcscfg_feature_desc{+constchar*name;+constchar*brief;+structlist_headitem;+u32match_flags;+intnr_params;+structcscfg_parameter_desc*params;+intnr_regs;+structcscfg_regval_desc*regs;+};++/**+*Matchdescriptor-Device/featurematchingwhenloadingintodevices+*+*Usedbyloadingconfigurationstodefinewhichclassorspecificdevices+*theywanttomatchusedfeaturesto,andregistereddevicestospecifywhich+*matchingclassandinformationtheysupport.+*+*Theloadprocessusesthesematchingpairstoloadfeatureinstancesinto+*matchingdevices.+*+*@match_flags:usedtomatchtoaparticularclassofdevice.+*+*/+structcscfg_match_desc{+u32match_flags;+};++/**+*Descriptorforfeaturesreferencedbyaconfiguration.+*+*@name:nameoffeaturetouse.Matchagainstthe@nameinstruct+*cscfg_feature_desc.+*@match:matchinfoforthefeaturewhenusedinthisconfiguration-+*maybealldevicesofaclassoraspecificdeviceinthatclass.+*/+structcscfg_config_feat_ref{+constchar*name;+structcscfg_match_descmatch;
I would get rid of structure cscfg_match_desc and put @match_flags right here.
How often do you envision features having different matches for different
configuration? If there is no real use for it we could use @name and
@match_flags from structure cscfg_feature_desck and get rid of
cscfg_config_feat_ref entirely.
I've been giving this some consideration - features really need the
match flags - they ensure hardware compatibility.
Configs - a simple select by name should be sufficient.
Both will need the ability to match to specific devices - e.g. a
system CTI will be connected differently than all the standard "cpu"
CTIs,
but this can be acheived for configurations at least by way of
extending the naming - e.g.
"feature" selects the feature on any device that supports it,
"feature.device" selects the feature on a specific device.
So yes - we can drop cscfg_config_feat_ref and probably
cscfg_match_desc as the match info will only appear in the
feature_desc.
quoted
+};
+
+/**
+ * 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 */
@@ -1739,13 +1740,22 @@ static int __init coresight_init(void)ret=etm_perf_init();if(ret)-bus_unregister(&coresight_bustype);+gotoexit_bus_unregister;+/* initialise the coresight syscfg API */+ret=cscfg_init();+if(!ret)+return0;++etm_perf_exit();+exit_bus_unregister:+bus_unregister(&coresight_bustype);returnret;}staticvoid__exitcoresight_exit(void){+cscfg_exit();etm_perf_exit();bus_unregister(&coresight_bustype);}
@@ -0,0 +1,197 @@+// SPDX-License-Identifier: GPL-2.0+/*+*Copyright(c)2020LinaroLimited,Allrightsreserved.+*Author:MikeLeach<mike.leach@linaro.org>+*/++#include<linux/platform_device.h>++#include"coresight-config.h"+#include"coresight-syscfg.h"++/*+*cscfg_APImanagesconfigurationsandfeaturesfortheentirecoresight+*infrastructure.+*+*Itallowstheloadingofconfigurationsandfeatures,andloadstheseinto+*coresightdevicesasappropriate.+*/++/* protect the cscsg_data and device */+staticDEFINE_MUTEX(cscfg_mutex);++/* only one of these */+staticstructcscfg_manager*cscfg_mgr;++/* load features and configuations into the lists */++/* check feature list for a named feature - call with mutex locked. */+staticboolcscfg_match_list_feat(constchar*name)+{+structcscfg_feature_desc*curr_item;++list_for_each_entry(curr_item,&cscfg_mgr->data.feat_desc_list,item){+if(strcmp(curr_item->name,name)==0)+returntrue;+}+returnfalse;+}++/* check all feat needed for cfg are in the list - call with mutex locked. */+staticintcscfg_check_feat_for_cfg(structcscfg_config_desc*cfg_desc)+{+inti;++for(i=0;i<cfg_desc->nr_refs;i++)+if(!cscfg_match_list_feat(cfg_desc->refs[i].name))+return-EINVAL;+return0;+}++/*+*loadfeature-addtofeaturelist.+*/+staticintcscfg_load_feat(structcscfg_feature_desc*feat_desc)+{+list_add(&feat_desc->item,&cscfg_mgr->data.feat_desc_list);++return0;+}++/*+*loadconfigintothesystem-validateusedfeaturesexistthenaddto+*configlist.+*/+staticintcscfg_load_config(structcscfg_config_desc*cfg_desc)+{+interr;++/* validate features are present */+err=cscfg_check_feat_for_cfg(cfg_desc);+if(err)+returnerr;++list_add(&cfg_desc->item,&cscfg_mgr->data.config_desc_list);++return0;+}++/*+*ExternalAPIfunctiontoloadfeatureandconfigsets.+*Takea0terminatedarrayoffeaturedescriptorsand/orconfiguration+*descriptorsandloadintothesystem.+*Featuresareloadedfirsttoensureconfigurationdependenciescanbemet.+*/+intcscfg_load_config_sets(structcscfg_config_desc**cfg_descs,+structcscfg_feature_desc**feat_descs)+{+interr,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);+gotodo_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);+gotodo_unlock;+}+i++;+}+}++do_unlock:+mutex_unlock(&cscfg_mutex);+returnerr;+}+EXPORT_SYMBOL_GPL(cscfg_load_config_sets);++/* Initialise system configuration management device. */++structdevice*to_device_cscfg(void)+{+returncscfg_mgr?&cscfg_mgr->dev:NULL;+}++/* Must have a release function or the kernel will complain on module unload */+voidcscfg_dev_release(structdevice*dev)+{+kfree(cscfg_mgr);+cscfg_mgr=NULL;+}++/* a device is needed to "own" some kernel elements such as sysfs entries. */+intcscfg_create_device(void)+{+structdevice*dev;+interr=-ENOMEM;++mutex_lock(&cscfg_mutex);+if(cscfg_mgr){+err=-EINVAL;+gotocreate_dev_exit_unlock;+}++cscfg_mgr=kzalloc(sizeof(structcscfg_manager),GFP_KERNEL);+if(!cscfg_mgr)+gotocreate_dev_exit_unlock;++/* setup the device */+dev=to_device_cscfg();+dev->release=cscfg_dev_release;+dev->init_name="system_cfg";++err=device_register(dev);+if(err)+cscfg_dev_release(dev);++create_dev_exit_unlock:+mutex_unlock(&cscfg_mutex);+returnerr;+}
We are keeping track of the number of cs devices registered with the manager but
I don't see a place (in this patchset) where the information is used. If indeed
we dont' need it I suggest moving the lists held in cscfg_api_data directly to
cscfg_manager.
No the count can be dropped. Its a hangover from some previously
dropped design feature. Now we have the manager object, there is no
value in the separate data object. I'll subsume the lists and other
things that end up in this sturcture directly into the manager.
@@ -0,0 +1,54 @@+/* SPDX-License-Identifier: GPL-2.0-only */+/*+*Coresightsystemconfigurationdriver.+*/++#ifndef CORESIGHT_SYSCFG_H+#define CORESIGHT_SYSCFG_H++#include<linux/coresight.h>+#include<linux/device.h>++#include"coresight-config.h"++/**+*SystemconfigurationmanagerAPIdata.+*+*@csdev_list:Listofcoresightdevicesregisteredwiththeconfigurationmanager.+*@feat_desc_list:Listoffeaturedescriptorstoloadintoregistereddevices.+*@config_desc_list:Listofsystemconfigurationdescriptorstoloadintoregistereddevices.+*@nr_csdev:Numberofregistereddeviceswiththecscfgsystem+*/+structcscfg_api_data{+structlist_headcsdev_desc_list;+structlist_headfeat_desc_list;+structlist_headconfig_desc_list;+intnr_csdev;+};++/* internal core operations for cscfg */+int__initcscfg_init(void);+void__exitcscfg_exit(void);++/* syscfg manager external API */+intcscfg_load_config_sets(structcscfg_config_desc**cfg_descs,+structcscfg_feature_desc**feat_descs);++/**+*Systemconfigurationmanagerdevice.+*+*Needadeviceto'own'somecoresightsystemwidesysfsentriesin+*perfevents,configfsetc.+*+*@dev:Thedevice.+*@data:TheAPIdata.+*/+structcscfg_manager{+structdevicedev;+structcscfg_api_datadata;+};++/* get reference to dev in cscfg_manager */+structdevice*to_device_cscfg(void);
This patch looks really good now. More comments to come tomorrow.
Thanks,
Mathieu
quoted
+
+#endif /* CORESIGHT_SYSCFG_H */
--
2.17.1
Thanks for the review
Mike
--
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
On Thu, Jan 28, 2021 at 05:09:27PM +0000, Mike Leach wrote:
quoted hunk
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 <redacted>
---
drivers/hwtracing/coresight/Makefile | 2 +-
.../hwtracing/coresight/coresight-config.h | 167 +++++++++++++++
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 | 197 ++++++++++++++++++
.../hwtracing/coresight/coresight-syscfg.h | 54 +++++
7 files changed, 432 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
@@ -0,0 +1,167 @@+/* SPDX-License-Identifier: GPL-2.0 */+/*+*Copyright(c)2020LinaroLimited,Allrightsreserved.+*Author:MikeLeach<mike.leach@linaro.org>+*/++#ifndef _CORESIGHT_CORESIGHT_CONFIG_H+#define _CORESIGHT_CORESIGHT_CONFIG_H++#include<linux/coresight.h>+#include<linux/types.h>++/* CoreSight Configuration Management - component and system wide configuration */++/*+*Registertypeflagsforregistervaluedescriptor:+*describehowthevalueisinterpreted,andhandled.+*/+#define CS_CFG_REG_TYPE_STD 0x80 /* reg is standard reg */+#define CS_CFG_REG_TYPE_RESOURCE 0x40 /* reg is a resource */+#define CS_CFG_REG_TYPE_VAL_PARAM 0x08 /* reg value uses param */+#define CS_CFG_REG_TYPE_VAL_MASK 0x04 /* reg value bit masked */+#define CS_CFG_REG_TYPE_VAL_64BIT 0x02 /* reg value 64 bit */+#define CS_CFG_REG_TYPE_VAL_SAVE 0x01 /* reg value save on disable */++/*+*flagsdefiningwhatdeviceclassafeaturewillmatchtowhenprocessinga+*systemconfiguration-usedbyconfigdataanddevices.+*/+#define CS_CFG_MATCH_CLASS_SRC_ALL 0x0001 /* match any source */+#define CS_CFG_MATCH_CLASS_SRC_ETM4 0x0002 /* match any ETMv4 device */++/* flags defining device instance matching - used in config match desc data. */+#define CS_CFG_MATCH_INST_ANY 0x80000000 /* any instance of a class */++/*+*Limitnumberofpresetsinaconfiguration+*Thisisrelatedtothenumberofbits(4)weusetoselectthepreseton+*theperfcommandline.Preset0isalwaysnoneselected.+*SeePMU_FORMAT_ATTR(preset,"config:0-3")incoresight-etm-perf.c+*/+#define CS_CFG_CONFIG_PRESET_MAX 15++/**+*Parameterdescriptorforadevicefeature.+*+*@name:Nameofparameter.+*@value:Initialordefaultvalue.+*/+structcscfg_parameter_desc{+constchar*name;+u64value;+};++/**+*Representationofregistervalue.+*+*Supportsfull64bitregistervalue,or32bitvaluewithoptionalmask+*value.+*+*@type:defineregisterusageandinterpretation.+*@offset:theaddressoffsetforregisterinthehardwaredevice(perdevicespecification).+*@hw_info:optionalhardwaredevicetypespecificinformation.(ETM/CTIspecificetc)+*@val64:64bitvalue.+*@val32:32bitvalue.+*@mask32:32bitmaskwhenusing32bitvaluetoaccessdeviceregister.+*/+structcscfg_regval_desc{+struct{+u32type:8;+u32offset:12;+u32hw_info:12;+};+union{+u64val64;+struct{+u32val32;+u32mask32;+};+};+};++/**+*Devicefeaturedescriptor-combinationofregistersandparametersto+*programadevicetoimplementaspecificcomplexfunction.+*+*@name:featurename.+*@brief:briefdescriptionofthefeature.+*@item:Listentry.+*@match_flags:matchinginformationifloadingintoadevice+*@nr_params:numberofparametersused.+*@params:arrayofparametersused.+*@nr_regs:numberofregistersused.+*@reg:arrayofregistersused.+*/+structcscfg_feature_desc{+constchar*name;+constchar*brief;+structlist_headitem;+u32match_flags;+intnr_params;+structcscfg_parameter_desc*params;
struct cscfg_parameter_desc *params_desc;
+ int nr_regs;
+ struct cscfg_regval_desc *regs;
struct cscfg_regval_desc *regs_desc;
That way I know exactly what I'm looking at when I see something like the
following in patch 03:
reg_desc = &feat->desc->regs[i];
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
From: Mike Leach <hidden> Date: 2021-02-26 19:11:51
Hi Mathieu,
On Mon, 22 Feb 2021 at 18:50, Mathieu Poirier
[off-list ref] wrote:
On Thu, Jan 28, 2021 at 05:09:27PM +0000, Mike Leach wrote:
quoted
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 <redacted>
---
drivers/hwtracing/coresight/Makefile | 2 +-
.../hwtracing/coresight/coresight-config.h | 167 +++++++++++++++
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 | 197 ++++++++++++++++++
.../hwtracing/coresight/coresight-syscfg.h | 54 +++++
7 files changed, 432 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
@@ -0,0 +1,167 @@+/* SPDX-License-Identifier: GPL-2.0 */+/*+*Copyright(c)2020LinaroLimited,Allrightsreserved.+*Author:MikeLeach<mike.leach@linaro.org>+*/++#ifndef _CORESIGHT_CORESIGHT_CONFIG_H+#define _CORESIGHT_CORESIGHT_CONFIG_H++#include<linux/coresight.h>+#include<linux/types.h>++/* CoreSight Configuration Management - component and system wide configuration */++/*+*Registertypeflagsforregistervaluedescriptor:+*describehowthevalueisinterpreted,andhandled.+*/+#define CS_CFG_REG_TYPE_STD 0x80 /* reg is standard reg */+#define CS_CFG_REG_TYPE_RESOURCE 0x40 /* reg is a resource */+#define CS_CFG_REG_TYPE_VAL_PARAM 0x08 /* reg value uses param */+#define CS_CFG_REG_TYPE_VAL_MASK 0x04 /* reg value bit masked */+#define CS_CFG_REG_TYPE_VAL_64BIT 0x02 /* reg value 64 bit */+#define CS_CFG_REG_TYPE_VAL_SAVE 0x01 /* reg value save on disable */++/*+*flagsdefiningwhatdeviceclassafeaturewillmatchtowhenprocessinga+*systemconfiguration-usedbyconfigdataanddevices.+*/+#define CS_CFG_MATCH_CLASS_SRC_ALL 0x0001 /* match any source */+#define CS_CFG_MATCH_CLASS_SRC_ETM4 0x0002 /* match any ETMv4 device */++/* flags defining device instance matching - used in config match desc data. */+#define CS_CFG_MATCH_INST_ANY 0x80000000 /* any instance of a class */++/*+*Limitnumberofpresetsinaconfiguration+*Thisisrelatedtothenumberofbits(4)weusetoselectthepreseton+*theperfcommandline.Preset0isalwaysnoneselected.+*SeePMU_FORMAT_ATTR(preset,"config:0-3")incoresight-etm-perf.c+*/+#define CS_CFG_CONFIG_PRESET_MAX 15++/**+*Parameterdescriptorforadevicefeature.+*+*@name:Nameofparameter.+*@value:Initialordefaultvalue.+*/+structcscfg_parameter_desc{+constchar*name;+u64value;+};++/**+*Representationofregistervalue.+*+*Supportsfull64bitregistervalue,or32bitvaluewithoptionalmask+*value.+*+*@type:defineregisterusageandinterpretation.+*@offset:theaddressoffsetforregisterinthehardwaredevice(perdevicespecification).+*@hw_info:optionalhardwaredevicetypespecificinformation.(ETM/CTIspecificetc)+*@val64:64bitvalue.+*@val32:32bitvalue.+*@mask32:32bitmaskwhenusing32bitvaluetoaccessdeviceregister.+*/+structcscfg_regval_desc{+struct{+u32type:8;+u32offset:12;+u32hw_info:12;+};+union{+u64val64;+struct{+u32val32;+u32mask32;+};+};+};++/**+*Devicefeaturedescriptor-combinationofregistersandparametersto+*programadevicetoimplementaspecificcomplexfunction.+*+*@name:featurename.+*@brief:briefdescriptionofthefeature.+*@item:Listentry.+*@match_flags:matchinginformationifloadingintoadevice+*@nr_params:numberofparametersused.+*@params:arrayofparametersused.+*@nr_regs:numberofregistersused.+*@reg:arrayofregistersused.+*/+structcscfg_feature_desc{+constchar*name;+constchar*brief;+structlist_headitem;+u32match_flags;+intnr_params;+structcscfg_parameter_desc*params;
struct cscfg_parameter_desc *params_desc;
quoted
+ int nr_regs;
+ struct cscfg_regval_desc *regs;
struct cscfg_regval_desc *regs_desc;
That way I know exactly what I'm looking at when I see something like the
following in patch 03:
reg_desc = &feat->desc->regs[i];
Agreed - I'll improve the naming consistency in the next revision
Mike
--
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
From: Suzuki K Poulose <suzuki.poulose@arm.com> Date: 2021-03-03 13:41:56
On 1/28/21 5:09 PM, Mike Leach wrote:
quoted hunk
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 <redacted>
---
drivers/hwtracing/coresight/Makefile | 2 +-
.../hwtracing/coresight/coresight-config.h | 167 +++++++++++++++
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 | 197 ++++++++++++++++++
.../hwtracing/coresight/coresight-syscfg.h | 54 +++++
7 files changed, 432 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
@@ -0,0 +1,167 @@+/* SPDX-License-Identifier: GPL-2.0 */+/*+*Copyright(c)2020LinaroLimited,Allrightsreserved.+*Author:MikeLeach<mike.leach@linaro.org>+*/++#ifndef _CORESIGHT_CORESIGHT_CONFIG_H+#define _CORESIGHT_CORESIGHT_CONFIG_H++#include<linux/coresight.h>+#include<linux/types.h>++/* CoreSight Configuration Management - component and system wide configuration */++/*+*Registertypeflagsforregistervaluedescriptor:+*describehowthevalueisinterpreted,andhandled.+*/+#define CS_CFG_REG_TYPE_STD 0x80 /* reg is standard reg */+#define CS_CFG_REG_TYPE_RESOURCE 0x40 /* reg is a resource */+#define CS_CFG_REG_TYPE_VAL_PARAM 0x08 /* reg value uses param */+#define CS_CFG_REG_TYPE_VAL_MASK 0x04 /* reg value bit masked */+#define CS_CFG_REG_TYPE_VAL_64BIT 0x02 /* reg value 64 bit */+#define CS_CFG_REG_TYPE_VAL_SAVE 0x01 /* reg value save on disable */++/*+*flagsdefiningwhatdeviceclassafeaturewillmatchtowhenprocessinga+*systemconfiguration-usedbyconfigdataanddevices.+*/+#define CS_CFG_MATCH_CLASS_SRC_ALL 0x0001 /* match any source */
nit: spurious TAB instead of SPACE
+#define CS_CFG_MATCH_CLASS_SRC_ETM4 0x0002 /* match any ETMv4 device */
+
+/* flags defining device instance matching - used in config match desc data. */
+#define CS_CFG_MATCH_INST_ANY 0x80000000 /* any instance of a class */
+
+/*
+ * Limit number of presets in a configuration
+ * This is related to the number of bits (4) we use to select the preset on
+ * the perf command line. Preset 0 is always none selected.
+ * See PMU_FORMAT_ATTR(preset, "config:0-3") in coresight-etm-perf.c
+ */
+#define CS_CFG_CONFIG_PRESET_MAX 15
+
+/**
+ * Parameter descriptor for a device feature.
+ *
+ * @name: Name of parameter.
+ * @value: Initial or default value.
+ */
+struct cscfg_parameter_desc {
+ const char *name;
+ u64 value;
+};
+
+/**
+ * Representation of register value.
+ *
+ * Supports full 64 bit register value, or 32 bit value with optional mask
+ * value.
+ *
+ * @type: define register usage and interpretation.
+ * @offset: the address offset for register in the hardware device (per device specification).
+ * @hw_info: optional hardware device type specific information. (ETM / CTI specific etc)
+ * @val64: 64 bit value.
+ * @val32: 32 bit value.
+ * @mask32: 32 bit mask when using 32 bit value to access device register.
+ */
+struct cscfg_regval_desc {
+ struct {
+ u32 type:8;
+ u32 offset:12;
+ u32 hw_info:12;
+ };
+ 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;
Either we could use the cscfg_match_desc here or, simply follow
inlining match_flags everywhere, below (e.g, cscfg_config_feat_ref)
+ int nr_params;
+ struct cscfg_parameter_desc *params;
+ int nr_regs;
+ struct cscfg_regval_desc *regs;
+};
+
+/**
+ * Match descriptor - Device / feature matching when loading into devices
+ *
+ * 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.
+ *
+ */
+struct cscfg_match_desc {
+ u32 match_flags;
+};
+
+/**
+ * Descriptor for features referenced by a configuration.
+ *
+ * @name: name of feature to use. Match against the @name in struct
+ * cscfg_feature_desc.
+ * @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;
+ struct cscfg_match_desc 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;
@@ -0,0 +1,197 @@+// SPDX-License-Identifier: GPL-2.0+/*+*Copyright(c)2020LinaroLimited,Allrightsreserved.+*Author:MikeLeach<mike.leach@linaro.org>+*/++#include<linux/platform_device.h>++#include"coresight-config.h"+#include"coresight-syscfg.h"++/*+*cscfg_APImanagesconfigurationsandfeaturesfortheentirecoresight+*infrastructure.+*+*Itallowstheloadingofconfigurationsandfeatures,andloadstheseinto+*coresightdevicesasappropriate.+*/++/* protect the cscsg_data and device */+staticDEFINE_MUTEX(cscfg_mutex);++/* only one of these */+staticstructcscfg_manager*cscfg_mgr;++/* load features and configuations into the lists */++/* check feature list for a named feature - call with mutex locked. */+staticboolcscfg_match_list_feat(constchar*name)+{+structcscfg_feature_desc*curr_item;++list_for_each_entry(curr_item,&cscfg_mgr->data.feat_desc_list,item){+if(strcmp(curr_item->name,name)==0)+returntrue;+}+returnfalse;+}++/* check all feat needed for cfg are in the list - call with mutex locked. */+staticintcscfg_check_feat_for_cfg(structcscfg_config_desc*cfg_desc)+{+inti;++for(i=0;i<cfg_desc->nr_refs;i++)+if(!cscfg_match_list_feat(cfg_desc->refs[i].name))+return-EINVAL;+return0;+}++/*+*loadfeature-addtofeaturelist.+*/+staticintcscfg_load_feat(structcscfg_feature_desc*feat_desc)+{+list_add(&feat_desc->item,&cscfg_mgr->data.feat_desc_list);++return0;+}++/*+*loadconfigintothesystem-validateusedfeaturesexistthenaddto+*configlist.+*/+staticintcscfg_load_config(structcscfg_config_desc*cfg_desc)+{+interr;++/* validate features are present */+err=cscfg_check_feat_for_cfg(cfg_desc);+if(err)+returnerr;++list_add(&cfg_desc->item,&cscfg_mgr->data.config_desc_list);++return0;+}++/*+*ExternalAPIfunctiontoloadfeatureandconfigsets.+*Takea0terminatedarrayoffeaturedescriptorsand/orconfiguration+*descriptorsandloadintothesystem.+*Featuresareloadedfirsttoensureconfigurationdependenciescanbemet.+*/+intcscfg_load_config_sets(structcscfg_config_desc**cfg_descs,+structcscfg_feature_desc**feat_descs)+{+interr,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);+gotodo_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);+gotodo_unlock;+}+i++;+}+}++do_unlock:+mutex_unlock(&cscfg_mutex);+returnerr;+}+EXPORT_SYMBOL_GPL(cscfg_load_config_sets);
It looks like we keep the features and configs in the global list,
even when there was a failure halfway. This could be problematic,
as the caller could release/free the nodes we added and walking
the list is going to explode. So, we either:
1) Do this in 2 pass. Check if the features and the configs can be
loaded in first pass. And load them in the second pass.
OR
2) Add cleanup code to remove the items that were added.
Since we do this with the mutex lock, we should be fine.
minor nit: to_device_cscfg() implies you are converting
something to a device. But since this is a global device
it could be better named as :
struct device *cscfg_device(void);
+{
+ return cscfg_mgr ? &cscfg_mgr->dev : NULL;
+}
+
+/* Must have a release function or the kernel will complain on module unload */
+void cscfg_dev_release(struct device *dev)
+{
+ kfree(cscfg_mgr);
+ cscfg_mgr = NULL;
+}
+
+/* a device is needed to "own" some kernel elements such as sysfs entries. */
+int cscfg_create_device(void)
+{
+ struct device *dev;
+ int err = -ENOMEM;
+
+ mutex_lock(&cscfg_mutex);
+ if (cscfg_mgr) {
+ err = -EINVAL;
+ goto create_dev_exit_unlock;
+ }
+
+ cscfg_mgr = kzalloc(sizeof(struct cscfg_manager), GFP_KERNEL);
+ if (!cscfg_mgr)
+ goto create_dev_exit_unlock;
+
+ /* setup the device */
+ dev = to_device_cscfg();
+ dev->release = cscfg_dev_release;
+ dev->init_name = "system_cfg";
nit: Does it make sense to have "cs" somewhere in the name ?
+ * @feat_desc_list: List of feature descriptors to load into registered devices.
+ * @config_desc_list: List of system configuration descriptors to load into registered devices.
+ * @nr_csdev: Number of registered devices with the cscfg system
+ */
+struct cscfg_api_data {
+ struct list_head csdev_desc_list;
+ struct list_head feat_desc_list;
+ struct list_head config_desc_list;
+ int nr_csdev;
+};
+
+/* internal core operations for cscfg */
+int __init cscfg_init(void);
+void __exit cscfg_exit(void);
+
+/* syscfg manager external API */
+int cscfg_load_config_sets(struct cscfg_config_desc **cfg_descs,
+ struct cscfg_feature_desc **feat_descs);
+
---> Cut here <---
+/**
+ * System configuration manager device.
+ *
+ * Need a device to 'own' some coresight system wide sysfs entries in
+ * perf events, configfs etc.
+ *
+ * @dev: The device.
+ * @data: The API data.
+ */
+struct cscfg_manager {
+ struct device dev;
+ struct cscfg_api_data data;
+};
+
+/* get reference to dev in cscfg_manager */
+struct device *to_device_cscfg(void);
--> Cut End <---
Do the above need to be exposed outside the core coresight-syscfg.c ?
Cheers
Suzuki
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
From: Mike Leach <hidden> Date: 2021-03-03 18:42:11
Hi Suzuki,
On Wed, 3 Mar 2021 at 10:09, Suzuki K Poulose [off-list ref] wrote:
On 1/28/21 5:09 PM, Mike Leach wrote:
quoted
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 <redacted>
---
drivers/hwtracing/coresight/Makefile | 2 +-
.../hwtracing/coresight/coresight-config.h | 167 +++++++++++++++
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 | 197 ++++++++++++++++++
.../hwtracing/coresight/coresight-syscfg.h | 54 +++++
7 files changed, 432 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
@@ -0,0 +1,167 @@+/* SPDX-License-Identifier: GPL-2.0 */+/*+*Copyright(c)2020LinaroLimited,Allrightsreserved.+*Author:MikeLeach<mike.leach@linaro.org>+*/++#ifndef _CORESIGHT_CORESIGHT_CONFIG_H+#define _CORESIGHT_CORESIGHT_CONFIG_H++#include<linux/coresight.h>+#include<linux/types.h>++/* CoreSight Configuration Management - component and system wide configuration */++/*+*Registertypeflagsforregistervaluedescriptor:+*describehowthevalueisinterpreted,andhandled.+*/+#define CS_CFG_REG_TYPE_STD 0x80 /* reg is standard reg */+#define CS_CFG_REG_TYPE_RESOURCE 0x40 /* reg is a resource */+#define CS_CFG_REG_TYPE_VAL_PARAM 0x08 /* reg value uses param */+#define CS_CFG_REG_TYPE_VAL_MASK 0x04 /* reg value bit masked */+#define CS_CFG_REG_TYPE_VAL_64BIT 0x02 /* reg value 64 bit */+#define CS_CFG_REG_TYPE_VAL_SAVE 0x01 /* reg value save on disable */++/*+*flagsdefiningwhatdeviceclassafeaturewillmatchtowhenprocessinga+*systemconfiguration-usedbyconfigdataanddevices.+*/+#define CS_CFG_MATCH_CLASS_SRC_ALL 0x0001 /* match any source */
nit: spurious TAB instead of SPACE
quoted
+#define CS_CFG_MATCH_CLASS_SRC_ETM4 0x0002 /* match any ETMv4 device */
+
+/* flags defining device instance matching - used in config match desc data. */
+#define CS_CFG_MATCH_INST_ANY 0x80000000 /* any instance of a class */
+
+/*
+ * Limit number of presets in a configuration
+ * This is related to the number of bits (4) we use to select the preset on
+ * the perf command line. Preset 0 is always none selected.
+ * See PMU_FORMAT_ATTR(preset, "config:0-3") in coresight-etm-perf.c
+ */
+#define CS_CFG_CONFIG_PRESET_MAX 15
+
+/**
+ * Parameter descriptor for a device feature.
+ *
+ * @name: Name of parameter.
+ * @value: Initial or default value.
+ */
+struct cscfg_parameter_desc {
+ const char *name;
+ u64 value;
+};
+
+/**
+ * Representation of register value.
+ *
+ * Supports full 64 bit register value, or 32 bit value with optional mask
+ * value.
+ *
+ * @type: define register usage and interpretation.
+ * @offset: the address offset for register in the hardware device (per device specification).
+ * @hw_info: optional hardware device type specific information. (ETM / CTI specific etc)
+ * @val64: 64 bit value.
+ * @val32: 32 bit value.
+ * @mask32: 32 bit mask when using 32 bit value to access device register.
+ */
+struct cscfg_regval_desc {
+ struct {
+ u32 type:8;
+ u32 offset:12;
+ u32 hw_info:12;
+ };
+ 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;
Either we could use the cscfg_match_desc here or, simply follow
inlining match_flags everywhere, below (e.g, cscfg_config_feat_ref)
Following Mathieus comments and a re-think on my part this will be
addressed in the re-spin. I am planning to drop cfg_config_feat_ref in
favour of mathing just by name in configs, and having discrete flags
(and later named devices) in the feat_desc.
quoted
+ int nr_params;
+ struct cscfg_parameter_desc *params;scfg_config_feat_ref
+ int nr_regs;
+ struct cscfg_regval_desc *regs;
+};
+
+/**
+ * Match descriptor - Device / feature matching when loading into devices
+ *
+ * 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.
+ *
+ */
+struct cscfg_match_desc {
+ u32 match_flags;
+};
+
+/**
+ * Descriptor for features referenced by a configuration.
+ *
+ * @name: name of feature to use. Match against the @name in struct
+ * cscfg_feature_desc.
+ * @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;
+ struct cscfg_match_desc 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;
super nit: s/brief/desc ?
Probably 'description' to avoid clash with all the _desc names, but yes.
@@ -0,0 +1,197 @@+// SPDX-License-Identifier: GPL-2.0+/*+*Copyright(c)2020LinaroLimited,Allrightsreserved.+*Author:MikeLeach<mike.leach@linaro.org>+*/++#include<linux/platform_device.h>++#include"coresight-config.h"+#include"coresight-syscfg.h"++/*+*cscfg_APImanagesconfigurationsandfeaturesfortheentirecoresight+*infrastructure.+*+*Itallowstheloadingofconfigurationsandfeatures,andloadstheseinto+*coresightdevicesasappropriate.+*/++/* protect the cscsg_data and device */+staticDEFINE_MUTEX(cscfg_mutex);++/* only one of these */+staticstructcscfg_manager*cscfg_mgr;++/* load features and configuations into the lists */++/* check feature list for a named feature - call with mutex locked. */+staticboolcscfg_match_list_feat(constchar*name)+{+structcscfg_feature_desc*curr_item;++list_for_each_entry(curr_item,&cscfg_mgr->data.feat_desc_list,item){+if(strcmp(curr_item->name,name)==0)+returntrue;+}+returnfalse;+}++/* check all feat needed for cfg are in the list - call with mutex locked. */+staticintcscfg_check_feat_for_cfg(structcscfg_config_desc*cfg_desc)+{+inti;++for(i=0;i<cfg_desc->nr_refs;i++)+if(!cscfg_match_list_feat(cfg_desc->refs[i].name))+return-EINVAL;+return0;+}++/*+*loadfeature-addtofeaturelist.+*/+staticintcscfg_load_feat(structcscfg_feature_desc*feat_desc)+{+list_add(&feat_desc->item,&cscfg_mgr->data.feat_desc_list);++return0;+}++/*+*loadconfigintothesystem-validateusedfeaturesexistthenaddto+*configlist.+*/+staticintcscfg_load_config(structcscfg_config_desc*cfg_desc)+{+interr;++/* validate features are present */+err=cscfg_check_feat_for_cfg(cfg_desc);+if(err)+returnerr;++list_add(&cfg_desc->item,&cscfg_mgr->data.config_desc_list);++return0;+}++/*+*ExternalAPIfunctiontoloadfeatureandconfigsets.+*Takea0terminatedarrayoffeaturedescriptorsand/orconfiguration+*descriptorsandloadintothesystem.+*Featuresareloadedfirsttoensureconfigurationdependenciescanbemet.+*/+intcscfg_load_config_sets(structcscfg_config_desc**cfg_descs,+structcscfg_feature_desc**feat_descs)+{+interr,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);+gotodo_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);+gotodo_unlock;+}+i++;+}+}++do_unlock:+mutex_unlock(&cscfg_mutex);+returnerr;+}+EXPORT_SYMBOL_GPL(cscfg_load_config_sets);
It looks like we keep the features and configs in the global list,
even when there was a failure halfway. This could be problematic,
as the caller could release/free the nodes we added and walking
the list is going to explode. So, we either:
1) Do this in 2 pass. Check if the features and the configs can be
loaded in first pass. And load them in the second pass.
OR
2) Add cleanup code to remove the items that were added.
Since we do this with the mutex lock, we should be fine.
In this initial set we are trying to keep to the minimum baseline to
provide the overall structure, with the autofdo configuration as a
built in.
Now we know that this configuration is by definition correct, so for
this baseline set at least, the code is guaranteed to work. We are not
allowing
additional user configs at this point.
There is a follow-up patch set that includes code to allow for dynamic
loading and unloading of configurations and features, and this
includes the correct error clean up, dependency locking to prevent
in-use configs from being unloaded, along with an example of how to
define a loadable module that loads a new set of configs / features.
But this adds a whole lot more code that is not needed in this
baseline set.
minor nit: to_device_cscfg() implies you are converting
something to a device. But since this is a global device
it could be better named as :
struct device *cscfg_device(void);
Agreed.
quoted
+{
+ return cscfg_mgr ? &cscfg_mgr->dev : NULL;
+}
+
+/* Must have a release function or the kernel will complain on module unload */
+void cscfg_dev_release(struct device *dev)
+{
+ kfree(cscfg_mgr);
+ cscfg_mgr = NULL;
+}
+
+/* a device is needed to "own" some kernel elements such as sysfs entries. */
+int cscfg_create_device(void)
+{
+ struct device *dev;
+ int err = -ENOMEM;
+
+ mutex_lock(&cscfg_mutex);
+ if (cscfg_mgr) {
+ err = -EINVAL;
+ goto create_dev_exit_unlock;
+ }
+
+ cscfg_mgr = kzalloc(sizeof(struct cscfg_manager), GFP_KERNEL);
+ if (!cscfg_mgr)
+ goto create_dev_exit_unlock;
+
+ /* setup the device */
+ dev = to_device_cscfg();
+ dev->release = cscfg_dev_release;
+ dev->init_name = "system_cfg";
nit: Does it make sense to have "cs" somewhere in the name ?
It does.
It's not something that the user would ever see / use, but no doubt
linux makes hte name visible in a list somewhere.
+ * @feat_desc_list: List of feature descriptors to load into registered devices.
+ * @config_desc_list: List of system configuration descriptors to load into registered devices.
+ * @nr_csdev: Number of registered devices with the cscfg system
+ */
+struct cscfg_api_data {
+ struct list_head csdev_desc_list;
+ struct list_head feat_desc_list;
+ struct list_head config_desc_list;
+ int nr_csdev;
+};
+
+/* internal core operations for cscfg */
+int __init cscfg_init(void);
+void __exit cscfg_exit(void);
+
+/* syscfg manager external API */
+int cscfg_load_config_sets(struct cscfg_config_desc **cfg_descs,
+ struct cscfg_feature_desc **feat_descs);
+
---> Cut here <---
quoted
+/**
+ * System configuration manager device.
+ *
+ * Need a device to 'own' some coresight system wide sysfs entries in
+ * perf events, configfs etc.
+ *
+ * @dev: The device.
+ * @data: The API data.
+ */
+struct cscfg_manager {
+ struct device dev;
+ struct cscfg_api_data data;
+};
+
+/* get reference to dev in cscfg_manager */
+struct device *to_device_cscfg(void);
--> Cut End <---
Do the above need to be exposed outside the core coresight-syscfg.c ?
Yes - they are used in the following patches in this set. They are
made visible here to avoid changing later in the patchset, which tends
to attract comments.
Cheers
Suzuki
Thanks for the review
Mike
--
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
From: Suzuki K Poulose <suzuki.poulose@arm.com> Date: 2021-03-03 14:51:24
On 1/28/21 5:09 PM, Mike Leach wrote:
quoted hunk
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 <redacted>
---
drivers/hwtracing/coresight/Makefile | 2 +-
.../hwtracing/coresight/coresight-config.h | 167 +++++++++++++++
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 | 197 ++++++++++++++++++
.../hwtracing/coresight/coresight-syscfg.h | 54 +++++
7 files changed, 432 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
@@ -0,0 +1,167 @@+/* SPDX-License-Identifier: GPL-2.0 */+/*+*Copyright(c)2020LinaroLimited,Allrightsreserved.+*Author:MikeLeach<mike.leach@linaro.org>+*/++#ifndef _CORESIGHT_CORESIGHT_CONFIG_H+#define _CORESIGHT_CORESIGHT_CONFIG_H++#include<linux/coresight.h>+#include<linux/types.h>++/* CoreSight Configuration Management - component and system wide configuration */++/*+*Registertypeflagsforregistervaluedescriptor:+*describehowthevalueisinterpreted,andhandled.+*/+#define CS_CFG_REG_TYPE_STD 0x80 /* reg is standard reg */+#define CS_CFG_REG_TYPE_RESOURCE 0x40 /* reg is a resource */+#define CS_CFG_REG_TYPE_VAL_PARAM 0x08 /* reg value uses param */+#define CS_CFG_REG_TYPE_VAL_MASK 0x04 /* reg value bit masked */+#define CS_CFG_REG_TYPE_VAL_64BIT 0x02 /* reg value 64 bit */+#define CS_CFG_REG_TYPE_VAL_SAVE 0x01 /* reg value save on disable */++/*+*flagsdefiningwhatdeviceclassafeaturewillmatchtowhenprocessinga+*systemconfiguration-usedbyconfigdataanddevices.+*/+#define CS_CFG_MATCH_CLASS_SRC_ALL 0x0001 /* match any source */+#define CS_CFG_MATCH_CLASS_SRC_ETM4 0x0002 /* match any ETMv4 device */++/* flags defining device instance matching - used in config match desc data. */+#define CS_CFG_MATCH_INST_ANY 0x80000000 /* any instance of a class */++/*+*Limitnumberofpresetsinaconfiguration+*Thisisrelatedtothenumberofbits(4)weusetoselectthepreseton+*theperfcommandline.Preset0isalwaysnoneselected.+*SeePMU_FORMAT_ATTR(preset,"config:0-3")incoresight-etm-perf.c+*/+#define CS_CFG_CONFIG_PRESET_MAX 15++/**+*Parameterdescriptorforadevicefeature.+*+*@name:Nameofparameter.+*@value:Initialordefaultvalue.+*/+structcscfg_parameter_desc{+constchar*name;+u64value;+};++/**+*Representationofregistervalue.+*+*Supportsfull64bitregistervalue,or32bitvaluewithoptionalmask+*value.+*+*@type:defineregisterusageandinterpretation.+*@offset:theaddressoffsetforregisterinthehardwaredevice(perdevicespecification).+*@hw_info:optionalhardwaredevicetypespecificinformation.(ETM/CTIspecificetc)+*@val64:64bitvalue.+*@val32:32bitvalue.+*@mask32:32bitmaskwhenusing32bitvaluetoaccessdeviceregister.+*/+structcscfg_regval_desc{+struct{+u32type:8;+u32offset:12;+u32hw_info:12;+};+union{+u64val64;+struct{+u32val32;+u32mask32;+};+};+};
Is it possible to indicate whether the register value is 64bit or 32bit within the
structure, rather than having this outside ? That way cscfg_regval_desc is a complete
entity. (Realized this while looking at patch 2)
Suzuki
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
From: Suzuki K Poulose <suzuki.poulose@arm.com> Date: 2021-03-04 10:10:39
On 1/28/21 5:09 PM, Mike Leach wrote:
quoted hunk
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 <redacted>
---
drivers/hwtracing/coresight/Makefile | 2 +-
.../hwtracing/coresight/coresight-config.h | 167 +++++++++++++++
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 | 197 ++++++++++++++++++
.../hwtracing/coresight/coresight-syscfg.h | 54 +++++
7 files changed, 432 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
@@ -0,0 +1,167 @@+/* SPDX-License-Identifier: GPL-2.0 */+/*+*Copyright(c)2020LinaroLimited,Allrightsreserved.+*Author:MikeLeach<mike.leach@linaro.org>+*/++#ifndef _CORESIGHT_CORESIGHT_CONFIG_H+#define _CORESIGHT_CORESIGHT_CONFIG_H++#include<linux/coresight.h>+#include<linux/types.h>++/* CoreSight Configuration Management - component and system wide configuration */++/*+*Registertypeflagsforregistervaluedescriptor:+*describehowthevalueisinterpreted,andhandled.+*/+#define CS_CFG_REG_TYPE_STD 0x80 /* reg is standard reg */+#define CS_CFG_REG_TYPE_RESOURCE 0x40 /* reg is a resource */+#define CS_CFG_REG_TYPE_VAL_PARAM 0x08 /* reg value uses param */+#define CS_CFG_REG_TYPE_VAL_MASK 0x04 /* reg value bit masked */+#define CS_CFG_REG_TYPE_VAL_64BIT 0x02 /* reg value 64 bit */+#define CS_CFG_REG_TYPE_VAL_SAVE 0x01 /* reg value save on disable */++/*+*flagsdefiningwhatdeviceclassafeaturewillmatchtowhenprocessinga+*systemconfiguration-usedbyconfigdataanddevices.+*/+#define CS_CFG_MATCH_CLASS_SRC_ALL 0x0001 /* match any source */+#define CS_CFG_MATCH_CLASS_SRC_ETM4 0x0002 /* match any ETMv4 device */++/* flags defining device instance matching - used in config match desc data. */+#define CS_CFG_MATCH_INST_ANY 0x80000000 /* any instance of a class */++/*+*Limitnumberofpresetsinaconfiguration+*Thisisrelatedtothenumberofbits(4)weusetoselectthepreseton+*theperfcommandline.Preset0isalwaysnoneselected.+*SeePMU_FORMAT_ATTR(preset,"config:0-3")incoresight-etm-perf.c+*/+#define CS_CFG_CONFIG_PRESET_MAX 15++/**+*Parameterdescriptorforadevicefeature.+*+*@name:Nameofparameter.+*@value:Initialordefaultvalue.+*/+structcscfg_parameter_desc{+constchar*name;+u64value;+};++/**+*Representationofregistervalue.+*+*Supportsfull64bitregistervalue,or32bitvaluewithoptionalmask+*value.+*+*@type:defineregisterusageandinterpretation.+*@offset:theaddressoffsetforregisterinthehardwaredevice(perdevicespecification).+*@hw_info:optionalhardwaredevicetypespecificinformation.(ETM/CTIspecificetc)+*@val64:64bitvalue.+*@val32:32bitvalue.+*@mask32:32bitmaskwhenusing32bitvaluetoaccessdeviceregister.+*/+structcscfg_regval_desc{+struct{+u32type:8;+u32offset:12;+u32hw_info:12;+};+union{+u64val64;+struct{+u32val32;+u32mask32;+};+};+};++/**+*Devicefeaturedescriptor-combinationofregistersandparametersto+*programadevicetoimplementaspecificcomplexfunction.+*+*@name:featurename.+*@brief:briefdescriptionofthefeature.+*@item:Listentry.+*@match_flags:matchinginformationifloadingintoadevice+*@nr_params:numberofparametersused.+*@params:arrayofparametersused.+*@nr_regs:numberofregistersused.+*@reg:arrayofregistersused.+*/+structcscfg_feature_desc{+constchar*name;+constchar*brief;+structlist_headitem;+u32match_flags;+intnr_params;+structcscfg_parameter_desc*params;+intnr_regs;+structcscfg_regval_desc*regs;+};++/**+*Matchdescriptor-Device/featurematchingwhenloadingintodevices+*+*Usedbyloadingconfigurationstodefinewhichclassorspecificdevices+*theywanttomatchusedfeaturesto,andregistereddevicestospecifywhich+*matchingclassandinformationtheysupport.+*+*Theloadprocessusesthesematchingpairstoloadfeatureinstancesinto+*matchingdevices.+*+*@match_flags:usedtomatchtoaparticularclassofdevice.+*+*/+structcscfg_match_desc{+u32match_flags;+};++/**+*Descriptorforfeaturesreferencedbyaconfiguration.+*+*@name:nameoffeaturetouse.Matchagainstthe@nameinstruct+*cscfg_feature_desc.+*@match:matchinfoforthefeaturewhenusedinthisconfiguration-+*maybealldevicesofaclassoraspecificdeviceinthatclass.+*/+structcscfg_config_feat_ref{+constchar*name;+structcscfg_match_descmatch;+};++/**+*Configurationdescriptor-describesselectablesystemconfiguration.+*+*Aconfigurationdescribesdevicefeaturesinuse,andmayprovidepreset+*valuesfortheparametersinthosefeatures.+*+*Asinglesetofpresetsisthesumoftheparametersdeclaredby+*allthefeaturesinuse-thisvalueis@nr_total_params.+*+*@name:nameoftheconfiguration-usedforselection.+*@brief:descriptionofthepurposeoftheconfiguration.+*@item:listentry.+*@nr_refs:Numberoffeaturesusedinthisconfiguration.+*@refs:referencestofeaturesusedinthisconfiguration..+*@nr_presets:Numberofsetsofpresetssuppliedbythisconfiguration.+*@nr_total_params:Sumofallparametersdeclaredbyusedfeatures+*@presets:Arrayofpresetvalues.+*+*/+structcscfg_config_desc{+constchar*name;+constchar*brief;+structlist_headitem;+intnr_refs;+structcscfg_config_feat_ref*refs;
s/refs/config_feat_refs/ ?
In general please name the fields to make it easier to infer the type, given
the number of structures we deal with, it becomes very difficult to track
while reading the code.
Cheers
Suzuki
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
From: Mike Leach <hidden> Date: 2021-03-04 10:49:35
Hi Suzuki,
On Thu, 4 Mar 2021 at 10:08, Suzuki K Poulose [off-list ref] wrote:
On 1/28/21 5:09 PM, Mike Leach wrote:
quoted
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 <redacted>
---
drivers/hwtracing/coresight/Makefile | 2 +-
.../hwtracing/coresight/coresight-config.h | 167 +++++++++++++++
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 | 197 ++++++++++++++++++
.../hwtracing/coresight/coresight-syscfg.h | 54 +++++
7 files changed, 432 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
@@ -0,0 +1,167 @@+/* SPDX-License-Identifier: GPL-2.0 */+/*+*Copyright(c)2020LinaroLimited,Allrightsreserved.+*Author:MikeLeach<mike.leach@linaro.org>+*/++#ifndef _CORESIGHT_CORESIGHT_CONFIG_H+#define _CORESIGHT_CORESIGHT_CONFIG_H++#include<linux/coresight.h>+#include<linux/types.h>++/* CoreSight Configuration Management - component and system wide configuration */++/*+*Registertypeflagsforregistervaluedescriptor:+*describehowthevalueisinterpreted,andhandled.+*/+#define CS_CFG_REG_TYPE_STD 0x80 /* reg is standard reg */+#define CS_CFG_REG_TYPE_RESOURCE 0x40 /* reg is a resource */+#define CS_CFG_REG_TYPE_VAL_PARAM 0x08 /* reg value uses param */+#define CS_CFG_REG_TYPE_VAL_MASK 0x04 /* reg value bit masked */+#define CS_CFG_REG_TYPE_VAL_64BIT 0x02 /* reg value 64 bit */+#define CS_CFG_REG_TYPE_VAL_SAVE 0x01 /* reg value save on disable */++/*+*flagsdefiningwhatdeviceclassafeaturewillmatchtowhenprocessinga+*systemconfiguration-usedbyconfigdataanddevices.+*/+#define CS_CFG_MATCH_CLASS_SRC_ALL 0x0001 /* match any source */+#define CS_CFG_MATCH_CLASS_SRC_ETM4 0x0002 /* match any ETMv4 device */++/* flags defining device instance matching - used in config match desc data. */+#define CS_CFG_MATCH_INST_ANY 0x80000000 /* any instance of a class */++/*+*Limitnumberofpresetsinaconfiguration+*Thisisrelatedtothenumberofbits(4)weusetoselectthepreseton+*theperfcommandline.Preset0isalwaysnoneselected.+*SeePMU_FORMAT_ATTR(preset,"config:0-3")incoresight-etm-perf.c+*/+#define CS_CFG_CONFIG_PRESET_MAX 15++/**+*Parameterdescriptorforadevicefeature.+*+*@name:Nameofparameter.+*@value:Initialordefaultvalue.+*/+structcscfg_parameter_desc{+constchar*name;+u64value;+};++/**+*Representationofregistervalue.+*+*Supportsfull64bitregistervalue,or32bitvaluewithoptionalmask+*value.+*+*@type:defineregisterusageandinterpretation.+*@offset:theaddressoffsetforregisterinthehardwaredevice(perdevicespecification).+*@hw_info:optionalhardwaredevicetypespecificinformation.(ETM/CTIspecificetc)+*@val64:64bitvalue.+*@val32:32bitvalue.+*@mask32:32bitmaskwhenusing32bitvaluetoaccessdeviceregister.+*/+structcscfg_regval_desc{+struct{+u32type:8;+u32offset:12;+u32hw_info:12;+};+union{+u64val64;+struct{+u32val32;+u32mask32;+};+};+};++/**+*Devicefeaturedescriptor-combinationofregistersandparametersto+*programadevicetoimplementaspecificcomplexfunction.+*+*@name:featurename.+*@brief:briefdescriptionofthefeature.+*@item:Listentry.+*@match_flags:matchinginformationifloadingintoadevice+*@nr_params:numberofparametersused.+*@params:arrayofparametersused.+*@nr_regs:numberofregistersused.+*@reg:arrayofregistersused.+*/+structcscfg_feature_desc{+constchar*name;+constchar*brief;+structlist_headitem;+u32match_flags;+intnr_params;+structcscfg_parameter_desc*params;+intnr_regs;+structcscfg_regval_desc*regs;+};++/**+*Matchdescriptor-Device/featurematchingwhenloadingintodevices+*+*Usedbyloadingconfigurationstodefinewhichclassorspecificdevices+*theywanttomatchusedfeaturesto,andregistereddevicestospecifywhich+*matchingclassandinformationtheysupport.+*+*Theloadprocessusesthesematchingpairstoloadfeatureinstancesinto+*matchingdevices.+*+*@match_flags:usedtomatchtoaparticularclassofdevice.+*+*/+structcscfg_match_desc{+u32match_flags;+};++/**+*Descriptorforfeaturesreferencedbyaconfiguration.+*+*@name:nameoffeaturetouse.Matchagainstthe@nameinstruct+*cscfg_feature_desc.+*@match:matchinfoforthefeaturewhenusedinthisconfiguration-+*maybealldevicesofaclassoraspecificdeviceinthatclass.+*/+structcscfg_config_feat_ref{+constchar*name;+structcscfg_match_descmatch;+};++/**+*Configurationdescriptor-describesselectablesystemconfiguration.+*+*Aconfigurationdescribesdevicefeaturesinuse,andmayprovidepreset+*valuesfortheparametersinthosefeatures.+*+*Asinglesetofpresetsisthesumoftheparametersdeclaredby+*allthefeaturesinuse-thisvalueis@nr_total_params.+*+*@name:nameoftheconfiguration-usedforselection.+*@brief:descriptionofthepurposeoftheconfiguration.+*@item:listentry.+*@nr_refs:Numberoffeaturesusedinthisconfiguration.+*@refs:referencestofeaturesusedinthisconfiguration..+*@nr_presets:Numberofsetsofpresetssuppliedbythisconfiguration.+*@nr_total_params:Sumofallparametersdeclaredbyusedfeatures+*@presets:Arrayofpresetvalues.+*+*/+structcscfg_config_desc{+constchar*name;+constchar*brief;+structlist_headitem;+intnr_refs;+structcscfg_config_feat_ref*refs;
s/refs/config_feat_refs/ ?
In general please name the fields to make it easier to infer the type, given
the number of structures we deal with, it becomes very difficult to track
while reading the code.
Mathieu made the same comment - I'm updating the naming convention for v5
Thanks
Mike
Cheers
Suzuki
--
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
From: Suzuki K Poulose <suzuki.poulose@arm.com> Date: 2021-03-04 10:50:22
On 1/28/21 5:09 PM, 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 <redacted>
+/**
+ * Representation of register value.
+ *
+ * Supports full 64 bit register value, or 32 bit value with optional mask
+ * value.
+ *
+ * @type: define register usage and interpretation.
+ * @offset: the address offset for register in the hardware device (per device specification).
+ * @hw_info: optional hardware device type specific information. (ETM / CTI specific etc)
+ * @val64: 64 bit value.
+ * @val32: 32 bit value.
+ * @mask32: 32 bit mask when using 32 bit value to access device register.
+ */
+struct cscfg_regval_desc {
+ struct {
+ u32 type:8;
+ u32 offset:12;
+ u32 hw_info:12;
+ };
+ union {
+ u64 val64;
+ struct {
+ u32 val32;
Since this is also overloaded with param_idx for VAL_PARAM type, please
make this explicit by doing something like this, to avoid having
to explain things in the code, undocumented here.
union {
u32 val32;
u32 param_idx;
};
Cheers
Suzuki
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
From: Mike Leach <hidden> Date: 2021-01-28 17:13:09
Adds a set of generic support functions that allow devices to set and save
features values on the device, and enable and disable configurations.
Additional functions for other common operations including feature
reset.
Signed-off-by: Mike Leach <redacted>
---
drivers/hwtracing/coresight/Makefile | 2 +-
.../hwtracing/coresight/coresight-config.c | 245 ++++++++++++++++++
.../hwtracing/coresight/coresight-config.h | 14 +-
.../hwtracing/coresight/coresight-syscfg.c | 5 +-
4 files changed, 262 insertions(+), 4 deletions(-)
create mode 100644 drivers/hwtracing/coresight/coresight-config.c
@@ -0,0 +1,245 @@+// SPDX-License-Identifier: GPL-2.0+/*+*Copyright(C)2020LinaroLimited.Allrightsreserved.+*Author:MikeLeach<mike.leach@linaro.org>+*/++#include<linux/sysfs.h>+#include"coresight-config.h"+#include"coresight-priv.h"++/*+*Writethevalueheldintheregisterstructureintothedriverinternalmemory+*location.+*/+staticvoidcscfg_set_reg(structcscfg_reg_csdev*reg)+{+u32*p_val32=(u32*)reg->drv_store;+u32tmp32=reg->value.val32;++if(reg->value.type&CS_CFG_REG_TYPE_VAL_64BIT){+*((u64*)reg->drv_store)=reg->value.val64;+return;+}++if(reg->value.type&CS_CFG_REG_TYPE_VAL_MASK){+tmp32=*p_val32;+tmp32&=~reg->value.mask32;+tmp32|=reg->value.val32®->value.mask32;+}+*p_val32=tmp32;+}++/*+*Readthedrivervalueintotheregifthisismarkedasonewewanttosave.+*/+staticvoidcscfg_save_reg(structcscfg_reg_csdev*reg)+{+if(!(reg->value.type&CS_CFG_REG_TYPE_VAL_SAVE))+return;+if(reg->value.type&CS_CFG_REG_TYPE_VAL_64BIT)+reg->value.val64=*(u64*)(reg->drv_store);+else+reg->value.val32=*(u32*)(reg->drv_store);+}++staticvoidcscfg_init_reg_param(structcscfg_parameter_csdev*param_csdev,+structcscfg_reg_csdev*reg_csdev)+{+param_csdev->reg=reg_csdev;+param_csdev->val64=reg_csdev->value.type&CS_CFG_REG_TYPE_VAL_64BIT;++if(param_csdev->val64)+param_csdev->reg->value.val64=param_csdev->current_value;+else+param_csdev->reg->value.val32=(u32)param_csdev->current_value;+}++/* set values into the driver locations referenced in cscfg_reg_csdev */+staticintcscfg_set_on_enable(structcscfg_feature_csdev*feat)+{+inti;++spin_lock(feat->csdev_spinlock);+for(i=0;i<feat->nr_regs;i++)+cscfg_set_reg(&feat->regs[i]);+spin_unlock(feat->csdev_spinlock);+dev_dbg(&feat->csdev->dev,"Feature %s: %s",feat->desc->name,"set on enable");+return0;+}++/* copy back values from the driver locations referenced in cscfg_reg_csdev */+staticvoidcscfg_save_on_disable(structcscfg_feature_csdev*feat)+{+inti;++spin_lock(feat->csdev_spinlock);+for(i=0;i<feat->nr_regs;i++)+cscfg_save_reg(&feat->regs[i]);+spin_unlock(feat->csdev_spinlock);+dev_dbg(&feat->csdev->dev,"Feature %s: %s",feat->desc->name,"save on disable");+}++/* default reset - restore default values */+voidcscfg_reset_feat(structcscfg_feature_csdev*feat)+{+structcscfg_parameter_csdev*param_csdev;+structcscfg_regval_desc*reg_desc;+structcscfg_reg_csdev*reg_csdev;+inti;++/*+*setthedefaultvaluesforallparametersandregsfromthe+*relevantstaticdescriptors.+*/+for(i=0;i<feat->nr_params;i++)+feat->params[i].current_value=feat->desc->params[i].value;++for(i=0;i<feat->nr_regs;i++){+reg_desc=&feat->desc->regs[i];+reg_csdev=&feat->regs[i];+reg_csdev->value.type=reg_desc->type;++/* check if reg set from a parameter otherwise desc default */+if(reg_desc->type&CS_CFG_REG_TYPE_VAL_PARAM){+/* for param, reg_desc->val32 is an index */+param_csdev=&feat->params[reg_desc->val32];+cscfg_init_reg_param(param_csdev,reg_csdev);+}else+reg_csdev->value.val64=reg_desc->val64;+}+}++staticintcscfg_update_presets(structcscfg_config_csdev*cfg,intpreset)+{+inti,j,line_offset=0,val_idx=0,max_idx;+structcscfg_parameter_csdev*param;+structcscfg_feature_csdev*feat;+constchar*name;+u64val;++if(preset>cfg->desc->nr_presets)+return-EINVAL;+/*+*Gothroughthearrayoffeatures,assigningpresetvaluesto+*featureparametersintheordertheyappear.+*Thereshouldbepreciselythesamenumberofpresetvaluesasthe+*sumofnumberofparametersoverallthefeatures-butwewill+*ensurethereisnooverrun.+*/+line_offset=(preset-1)*cfg->desc->nr_total_params;+max_idx=cfg->desc->nr_total_params;+for(i=0;i<cfg->nr_feat;i++){+feat=cfg->feats[i];+if(!feat->nr_params)+continue;++for(j=0;j<feat->nr_params;j++){+param=&feat->params[j];+name=feat->desc->params[j].name;+val=cfg->desc->presets[line_offset+val_idx++];+if(param->val64){+dev_dbg(&cfg->csdev->dev,+"set param %s (%lld)",name,val);+param->reg->value.val64=val;+}else{+param->reg->value.val32=(u32)val;+dev_dbg(&cfg->csdev->dev,+"set param %s (%d)",name,(u32)val);+}+if(val_idx>=max_idx)+break;+}++/* don't overrun the preset array line */+if(val_idx>=max_idx)+break;+}+return0;+}++/*+*ifwearenotusingapreset,thenneedtoupdatethefeatureparams+*withcurrentvalues.+*/+staticintcscfg_update_curr_params(structcscfg_config_csdev*cfg)+{+inti,j;+structcscfg_feature_csdev*feat;+structcscfg_parameter_csdev*param;+constchar*name;+u64val;++for(i=0;i<cfg->nr_feat;i++){+feat=cfg->feats[i];+if(!feat->nr_params)+continue;+for(j=0;j<feat->nr_params;j++){+param=&feat->params[j];+name=feat->desc->params[j].name;+val=param->current_value;+if(param->val64){+dev_dbg(&cfg->csdev->dev,+"set param %s (%lld)",name,val);+param->reg->value.val64=val;+}else{+param->reg->value.val32=(u32)val;+dev_dbg(&cfg->csdev->dev,+"set param %s (%d)",name,(u32)val);+}+}+}+return0;+}++staticintcscfg_prog_config(structcscfg_config_csdev*cfg,boolenable)+{+inti,err=0;+structcscfg_feature_csdev*feat;+structcoresight_device*csdev;++for(i=0;i<cfg->nr_feat;i++){+feat=cfg->feats[i];+csdev=feat->csdev;+dev_dbg(&csdev->dev,"cfg %s; %s feature:%s",cfg->desc->name,+enable?"enable":"disable",feat->desc->name);++if(enable)+err=cscfg_set_on_enable(feat);+else+cscfg_save_on_disable(feat);++if(err)+break;+}+returnerr;+}++/**+*Enableconfigurationforthedevice.+*+*@cfg:config_csdevtoset.+*@preset:presetvaluestouse-0fordefault.+*/+intcscfg_csdev_enable_config(structcscfg_config_csdev*cfg,intpreset)+{+interr=0;++if(preset)+err=cscfg_update_presets(cfg,preset);+else+err=cscfg_update_curr_params(cfg);+if(!err)+err=cscfg_prog_config(cfg,true);+if(!err)+cfg->enabled=true;+returnerr;+}++voidcscfg_csdev_disable_config(structcscfg_config_csdev*cfg)+{+if(cfg->enabled){+cscfg_prog_config(cfg,false);+cfg->enabled=false;+}+}
@@ -198,14 +198,15 @@ static int cscfg_load_feat_csdev(struct coresight_device *csdev,if(!feat_csdev)return-ENOMEM;-/* load the feature into the device - may modify default ops*/+/* load the feature into the device */err=ops->load_feat(csdev,feat_csdev);if(err)returnerr;-/* add to internal csdev feature list */+/* add to internal csdev feature list & initialise using reset call */mutex_lock(&cscfg_csdev_mutex);list_add(&feat_csdev->node,&csdev->feature_csdev_list);+cscfg_reset_feat(feat_csdev);mutex_unlock(&cscfg_csdev_mutex);return0;
--
2.17.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
On Thu, Jan 28, 2021 at 05:09:29PM +0000, Mike Leach wrote:
quoted hunk
Adds a set of generic support functions that allow devices to set and save
features values on the device, and enable and disable configurations.
Additional functions for other common operations including feature
reset.
Signed-off-by: Mike Leach <redacted>
---
drivers/hwtracing/coresight/Makefile | 2 +-
.../hwtracing/coresight/coresight-config.c | 245 ++++++++++++++++++
.../hwtracing/coresight/coresight-config.h | 14 +-
.../hwtracing/coresight/coresight-syscfg.c | 5 +-
4 files changed, 262 insertions(+), 4 deletions(-)
create mode 100644 drivers/hwtracing/coresight/coresight-config.c
This is the link between registers and parameters... Very important and very
easy to miss. I'm not use how the situation can be improved other than adding a
comment to highlight the dependency.
+ param_csdev->val64 = reg_csdev->value.type & CS_CFG_REG_TYPE_VAL_64BIT;
+
+ if (param_csdev->val64)
+ param_csdev->reg->value.val64 = param_csdev->current_value;
+ else
+ param_csdev->reg->value.val32 = (u32)param_csdev->current_value;
+}
+
+/* set values into the driver locations referenced in cscfg_reg_csdev */
+static int cscfg_set_on_enable(struct cscfg_feature_csdev *feat)
+{
+ int i;
+
+ spin_lock(feat->csdev_spinlock);
+ for (i = 0; i < feat->nr_regs; i++)
+ cscfg_set_reg(&feat->regs[i]);
+ spin_unlock(feat->csdev_spinlock);
+ dev_dbg(&feat->csdev->dev, "Feature %s: %s", feat->desc->name, "set on enable");
+ return 0;
+}
+
+/* copy back values from the driver locations referenced in cscfg_reg_csdev */
+static void cscfg_save_on_disable(struct cscfg_feature_csdev *feat)
static void cscfg_save_on_disable(struct cscfg_feature_csdev *feat_csdev)
To be modified throughout the patchset.
+{
+ int i;
+
+ spin_lock(feat->csdev_spinlock);
+ for (i = 0; i < feat->nr_regs; i++)
+ cscfg_save_reg(&feat->regs[i]);
+ spin_unlock(feat->csdev_spinlock);
+ dev_dbg(&feat->csdev->dev, "Feature %s: %s", feat->desc->name, "save on disable");
+}
+
+/* default reset - restore default values */
+void cscfg_reset_feat(struct cscfg_feature_csdev *feat)
+{
+ struct cscfg_parameter_csdev *param_csdev;
+ struct cscfg_regval_desc *reg_desc;
+ struct cscfg_reg_csdev *reg_csdev;
+ int i;
+
+ /*
+ * set the default values for all parameters and regs from the
+ * relevant static descriptors.
+ */
+ for (i = 0; i < feat->nr_params; i++)
+ feat->params[i].current_value = feat->desc->params[i].value;
+
+ for (i = 0; i < feat->nr_regs; i++) {
+ reg_desc = &feat->desc->regs[i];
+ reg_csdev = &feat->regs[i];
+ reg_csdev->value.type = reg_desc->type;
+
+ /* check if reg set from a parameter otherwise desc default */
+ if (reg_desc->type & CS_CFG_REG_TYPE_VAL_PARAM) {
+ /* for param, reg_desc->val32 is an index */
Overloading reg_desc->val32 into an index will make maintenance of this code
impossible. Please see if there is a way to make that more intuitive.
+ /*
+ * Go through the array of features, assigning preset values to
+ * feature parameters in the order they appear.
+ * There should be precisely the same number of preset values as the
+ * sum of number of parameters over all the features - but we will
+ * ensure there is no overrun.
+ */
+ line_offset = (preset-1) * cfg->desc->nr_total_params;
@@ -198,14 +198,15 @@ static int cscfg_load_feat_csdev(struct coresight_device *csdev,if(!feat_csdev)return-ENOMEM;-/* load the feature into the device - may modify default ops*/+/* load the feature into the device */
The right comment should be added in patch 02 and not changed without code to
sustain it.
A rigorous and consistent naming convention is of prime importance in this
patch. Otherwise I think it is holding together well.
More comments tomorrow.
Thanks,
Mathieu
err = ops->load_feat(csdev, feat_csdev);
if (err)
return err;
- /* add to internal csdev feature list */
+ /* add to internal csdev feature list & initialise using reset call */
mutex_lock(&cscfg_csdev_mutex);
list_add(&feat_csdev->node, &csdev->feature_csdev_list);
+ cscfg_reset_feat(feat_csdev);
mutex_unlock(&cscfg_csdev_mutex);
return 0;
--
2.17.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
From: Suzuki K Poulose <suzuki.poulose@arm.com> Date: 2021-03-04 11:27:02
On 1/28/21 5:09 PM, Mike Leach wrote:
quoted hunk
Adds a set of generic support functions that allow devices to set and save
features values on the device, and enable and disable configurations.
Additional functions for other common operations including feature
reset.
Signed-off-by: Mike Leach <redacted>
---
drivers/hwtracing/coresight/Makefile | 2 +-
.../hwtracing/coresight/coresight-config.c | 245 ++++++++++++++++++
.../hwtracing/coresight/coresight-config.h | 14 +-
.../hwtracing/coresight/coresight-syscfg.c | 5 +-
4 files changed, 262 insertions(+), 4 deletions(-)
create mode 100644 drivers/hwtracing/coresight/coresight-config.c
It may be good to add a one-or-two line summary of what this file is
all about in general.
+ */
+
+#include <linux/sysfs.h>
+#include "coresight-config.h"
+#include "coresight-priv.h"
+
+/*
+ * Write the value held in the register structure into the driver internal memory
+ * location.
+ */
+static void cscfg_set_reg(struct cscfg_reg_csdev *reg)
+{
+ u32 *p_val32 = (u32 *)reg->drv_store;
Could we rename drv_store to something slightly more intuitive ?
reg->cache ? or reg->current_val ?
+ u32 tmp32 = reg->value.val32;
+
+ if (reg->value.type & CS_CFG_REG_TYPE_VAL_64BIT) {
+ *((u64 *)reg->drv_store) = reg->value.val64;
+ return;
+ }
+
+ if (reg->value.type & CS_CFG_REG_TYPE_VAL_MASK) {
+ tmp32 = *p_val32;
+ tmp32 &= ~reg->value.mask32;
+ tmp32 |= reg->value.val32 & reg->value.mask32;
+ }
+ *p_val32 = tmp32;
+}
+
+/*
+ * Read the driver value into the reg if this is marked as one we want to save.
+ */
+static void cscfg_save_reg(struct cscfg_reg_csdev *reg)
+{
+ if (!(reg->value.type & CS_CFG_REG_TYPE_VAL_SAVE))
+ return;
+ if (reg->value.type & CS_CFG_REG_TYPE_VAL_64BIT)
+ reg->value.val64 = *(u64 *)(reg->drv_store);
+ else
+ reg->value.val32 = *(u32 *)(reg->drv_store);
+}
+
+static void cscfg_init_reg_param(struct cscfg_parameter_csdev *param_csdev,
+ struct cscfg_reg_csdev *reg_csdev)
+{
+ param_csdev->reg = reg_csdev;
+ param_csdev->val64 = reg_csdev->value.type & CS_CFG_REG_TYPE_VAL_64BIT;
+
+ if (param_csdev->val64)
+ param_csdev->reg->value.val64 = param_csdev->current_value;
+ else
+ param_csdev->reg->value.val32 = (u32)param_csdev->current_value;
+}
+
+/* set values into the driver locations referenced in cscfg_reg_csdev */
+static int cscfg_set_on_enable(struct cscfg_feature_csdev *feat)
+{
+ int i;
+
+ spin_lock(feat->csdev_spinlock);
+ for (i = 0; i < feat->nr_regs; i++)
+ cscfg_set_reg(&feat->regs[i]);
+ spin_unlock(feat->csdev_spinlock);
+ dev_dbg(&feat->csdev->dev, "Feature %s: %s", feat->desc->name, "set on enable");
+ return 0;
+}
+
+/* copy back values from the driver locations referenced in cscfg_reg_csdev */
+static void cscfg_save_on_disable(struct cscfg_feature_csdev *feat)
+{
+ int i;
+
+ spin_lock(feat->csdev_spinlock);
+ for (i = 0; i < feat->nr_regs; i++)
+ cscfg_save_reg(&feat->regs[i]);
+ spin_unlock(feat->csdev_spinlock);
+ dev_dbg(&feat->csdev->dev, "Feature %s: %s", feat->desc->name, "save on disable");
+}
+
+/* default reset - restore default values */
+void cscfg_reset_feat(struct cscfg_feature_csdev *feat)
+{
+ struct cscfg_parameter_csdev *param_csdev;
+ struct cscfg_regval_desc *reg_desc;
+ struct cscfg_reg_csdev *reg_csdev;
+ int i;
+
+ /*
+ * set the default values for all parameters and regs from the
+ * relevant static descriptors.
+ */
+ for (i = 0; i < feat->nr_params; i++)
+ feat->params[i].current_value = feat->desc->params[i].value;
+
+ for (i = 0; i < feat->nr_regs; i++) {
+ reg_desc = &feat->desc->regs[i];
+ reg_csdev = &feat->regs[i];
+ reg_csdev->value.type = reg_desc->type;
+
+ /* check if reg set from a parameter otherwise desc default */
+ if (reg_desc->type & CS_CFG_REG_TYPE_VAL_PARAM) {
+ /* for param, reg_desc->val32 is an index */
+ param_csdev = &feat->params[reg_desc->val32];
Please add val32 to a union, as suggested in response to Patch 1. Also, please make
sure the idx is within the nr_params range. I suggest move this into cscfg_init_reg_param
and have this contained there.
+ cscfg_init_reg_param(param_csdev, reg_csdev);
+ } else
+ reg_csdev->value.val64 = reg_desc->val64;
+ }
+}
+
+static int cscfg_update_presets(struct cscfg_config_csdev *cfg, int preset)
+{
+ int i, j, line_offset = 0, val_idx = 0, max_idx;
+ struct cscfg_parameter_csdev *param;
+ struct cscfg_feature_csdev *feat;
+ const char *name;
+ u64 val;
+
+ if (preset > cfg->desc->nr_presets)
+ return -EINVAL;
+ /*
+ * Go through the array of features, assigning preset values to
+ * feature parameters in the order they appear.
+ * There should be precisely the same number of preset values as the
+ * sum of number of parameters over all the features - but we will
+ * ensure there is no overrun.
+ */
+ line_offset = (preset-1) * cfg->desc->nr_total_params;
Could we instead do :
u64 *preset_base = &cfg->desc->presets[ (preset - 1) * cfg->desc->nr_total_params];
+ max_idx = cfg->desc->nr_total_params;
s/max_idx/n_params/
s/val_idx/param_idx/
+ for (i = 0; i < cfg->nr_feat; i++) {
+ feat = cfg->feats[i];
+ if (!feat->nr_params)
+ continue;
+
+ for (j = 0; j < feat->nr_params; j++) {
+ param = &feat->params[j];
+ name = feat->desc->params[j].name;
+ val = cfg->desc->presets[line_offset + val_idx++];
Isn't that an error if we overrun the nr_parameters ? And should we WARN about it ?
+ }
+ return 0;
+}
+
+/*
+ * if we are not using a preset, then need to update the feature params
+ * with current values.
+ */
+static int cscfg_update_curr_params(struct cscfg_config_csdev *cfg)
@@ -198,14 +198,15 @@ static int cscfg_load_feat_csdev(struct coresight_device *csdev,if(!feat_csdev)return-ENOMEM;-/* load the feature into the device - may modify default ops*/
Spurious change ?
+ /* load the feature into the device */
err = ops->load_feat(csdev, feat_csdev);
if (err)
return err;
- /* add to internal csdev feature list */
+ /* add to internal csdev feature list & initialise using reset call */
mutex_lock(&cscfg_csdev_mutex);
list_add(&feat_csdev->node, &csdev->feature_csdev_list);
+ cscfg_reset_feat(feat_csdev);
mutex_unlock(&cscfg_csdev_mutex);
return 0;
From: Mike Leach <hidden> Date: 2021-01-28 17:15:04
Adds in handlers to allow the ETMv4 to use the complex configuration
support. Features and configurations can be loaded and selected in the
device.
Signed-off-by: Mike Leach <redacted>
---
drivers/hwtracing/coresight/Makefile | 3 +-
.../hwtracing/coresight/coresight-etm4x-cfg.c | 184 ++++++++++++++++++
.../hwtracing/coresight/coresight-etm4x-cfg.h | 29 +++
.../coresight/coresight-etm4x-core.c | 38 +++-
.../coresight/coresight-etm4x-sysfs.c | 3 +
5 files changed, 254 insertions(+), 3 deletions(-)
create mode 100644 drivers/hwtracing/coresight/coresight-etm4x-cfg.c
create mode 100644 drivers/hwtracing/coresight/coresight-etm4x-cfg.h
@@ -491,12 +493,15 @@ static int etm4_config_timestamp_event(struct etmv4_drvdata *drvdata)returnret;}-staticintetm4_parse_event_config(structetmv4_drvdata*drvdata,+staticintetm4_parse_event_config(structcoresight_device*csdev,structperf_event*event){intret=0;+structetmv4_drvdata*drvdata=dev_get_drvdata(csdev->dev.parent);structetmv4_config*config=&drvdata->config;structperf_event_attr*attr=&event->attr;+unsignedlongcfg_id;+intpreset;if(!attr){ret=-EINVAL;
@@ -554,6 +559,20 @@ static int etm4_parse_event_config(struct etmv4_drvdata *drvdata,/* bit[12], Return stack enable bit */config->cfg|=BIT(12);+/*+*Setanyselectedconfigurationandpreset.+*+*ThisextractsthevaluesofPMU_FORMAT_ATTR(configid)andPMU_FORMAT_ATTR(preset)+*intheperfattributesdefinedincoresight-etm-perf.c.+*configidusesbits63:32ofattr->config2,presetusesbits3:0ofattr->config.+*Azeroconfigidmeansnoconfigurationactive,preset=0meansnopresetselected.+*/+if(attr->config2&GENMASK_ULL(63,32)){+cfg_id=(u32)(attr->config2>>32);+preset=attr->config&0xF;+ret=cscfg_csdev_enable_active_config(csdev,cfg_id,preset);+}+out:returnret;}
@@ -570,7 +589,7 @@ static int etm4_enable_perf(struct coresight_device *csdev,}/* Configure the tracer based on the session's specifics */-ret=etm4_parse_event_config(drvdata,event);+ret=etm4_parse_event_config(csdev,event);if(ret)gotoout;/* And enable it */
@@ -701,11 +720,18 @@ static int etm4_disable_perf(struct coresight_device *csdev,u32control;structetm_filters*filters=event->hw.addr_filters;structetmv4_drvdata*drvdata=dev_get_drvdata(csdev->dev.parent);+structperf_event_attr*attr=&event->attr;if(WARN_ON_ONCE(drvdata->cpu!=smp_processor_id()))return-EINVAL;etm4_disable_hw(drvdata);+/*+*Theconfig_idoccupiesbits63:32oftheconfig2perfeventattr+*field.Ifthisisnon-zerothenwewillhaveenabledaconfig.+*/+if(attr->config2&GENMASK_ULL(63,32))+cscfg_csdev_disable_active_config(csdev);/**Checkifthestart/stoplogicwasactivewhentheunitwasstopped.
@@ -1815,6 +1841,13 @@ static int etm4_probe(struct device *dev, void __iomem *base, u32 etm_pid)returnret;}+/* register with config infrastructure & load any current features */+ret=etm4_cscfg_register(drvdata->csdev,dev_name(dev));+if(ret){+coresight_unregister(drvdata->csdev);+returnret;+}+etmdrvdata[drvdata->cpu]=drvdata;dev_info(&drvdata->csdev->dev,"CPU%d: ETM v%d.%d initialized\n",
@@ -1902,6 +1935,7 @@ static int __exit etm4_remove_dev(struct etmv4_drvdata *drvdata)cpus_read_unlock();+cscfg_unregister_csdev(drvdata->csdev);coresight_unregister(drvdata->csdev);return0;
On Thu, Jan 28, 2021 at 05:09:33PM +0000, Mike Leach wrote:
quoted hunk
Adds in handlers to allow the ETMv4 to use the complex configuration
support. Features and configurations can be loaded and selected in the
device.
Signed-off-by: Mike Leach <redacted>
---
drivers/hwtracing/coresight/Makefile | 3 +-
.../hwtracing/coresight/coresight-etm4x-cfg.c | 184 ++++++++++++++++++
.../hwtracing/coresight/coresight-etm4x-cfg.h | 29 +++
.../coresight/coresight-etm4x-core.c | 38 +++-
.../coresight/coresight-etm4x-sysfs.c | 3 +
5 files changed, 254 insertions(+), 3 deletions(-)
create mode 100644 drivers/hwtracing/coresight/coresight-etm4x-cfg.c
create mode 100644 drivers/hwtracing/coresight/coresight-etm4x-cfg.h
@@ -491,12 +493,15 @@ static int etm4_config_timestamp_event(struct etmv4_drvdata *drvdata)returnret;}-staticintetm4_parse_event_config(structetmv4_drvdata*drvdata,+staticintetm4_parse_event_config(structcoresight_device*csdev,structperf_event*event){intret=0;+structetmv4_drvdata*drvdata=dev_get_drvdata(csdev->dev.parent);structetmv4_config*config=&drvdata->config;structperf_event_attr*attr=&event->attr;+unsignedlongcfg_id;+intpreset;
Ok
quoted hunk
if (!attr) {
ret = -EINVAL;
@@ -554,6 +559,20 @@ static int etm4_parse_event_config(struct etmv4_drvdata *drvdata, /* bit[12], Return stack enable bit */ config->cfg |= BIT(12);+ /*+ * Set any selected configuration and preset.+ *+ * This extracts the values of PMU_FORMAT_ATTR(configid) and PMU_FORMAT_ATTR(preset)+ * in the perf attributes defined in coresight-etm-perf.c.+ * configid uses bits 63:32 of attr->config2, preset uses bits 3:0 of attr->config.+ * A zero configid means no configuration active, preset = 0 means no preset selected.+ */+ if (attr->config2 & GENMASK_ULL(63, 32)) {+ cfg_id = (u32)(attr->config2 >> 32);+ preset = attr->config & 0xF;+ ret = cscfg_csdev_enable_active_config(csdev, cfg_id, preset);+ }+
Ok
quoted hunk
out:
return ret;
}
@@ -570,7 +589,7 @@ static int etm4_enable_perf(struct coresight_device *csdev, } /* Configure the tracer based on the session's specifics */- ret = etm4_parse_event_config(drvdata, event);+ ret = etm4_parse_event_config(csdev, event); if (ret) goto out; /* And enable it */
@@ -701,11 +720,18 @@ static int etm4_disable_perf(struct coresight_device *csdev, u32 control; struct etm_filters *filters = event->hw.addr_filters; struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);+ struct perf_event_attr *attr = &event->attr; if (WARN_ON_ONCE(drvdata->cpu != smp_processor_id())) return -EINVAL; etm4_disable_hw(drvdata);+ /*+ * The config_id occupies bits 63:32 of the config2 perf event attr+ * field. If this is non-zero then we will have enabled a config.+ */+ if (attr->config2 & GENMASK_ULL(63, 32))+ cscfg_csdev_disable_active_config(csdev);
Ok
quoted hunk
/*
* Check if the start/stop logic was active when the unit was stopped.
@@ -1815,6 +1841,13 @@ static int etm4_probe(struct device *dev, void __iomem *base, u32 etm_pid) return ret; }+ /* register with config infrastructure & load any current features */+ ret = etm4_cscfg_register(drvdata->csdev, dev_name(dev));+ if (ret) {+ coresight_unregister(drvdata->csdev);+ return ret;+ }+ etmdrvdata[drvdata->cpu] = drvdata; dev_info(&drvdata->csdev->dev, "CPU%d: ETM v%d.%d initialized\n",
From: Suzuki K Poulose <suzuki.poulose@arm.com> Date: 2021-03-05 10:19:02
On 1/28/21 5:09 PM, Mike Leach wrote:
quoted hunk
Adds in handlers to allow the ETMv4 to use the complex configuration
support. Features and configurations can be loaded and selected in the
device.
Signed-off-by: Mike Leach <redacted>
---
drivers/hwtracing/coresight/Makefile | 3 +-
.../hwtracing/coresight/coresight-etm4x-cfg.c | 184 ++++++++++++++++++
.../hwtracing/coresight/coresight-etm4x-cfg.h | 29 +++
.../coresight/coresight-etm4x-core.c | 38 +++-
.../coresight/coresight-etm4x-sysfs.c | 3 +
5 files changed, 254 insertions(+), 3 deletions(-)
create mode 100644 drivers/hwtracing/coresight/coresight-etm4x-cfg.c
create mode 100644 drivers/hwtracing/coresight/coresight-etm4x-cfg.h
I think we can live with switch-case, ignoring the Warnings generated by the
checkpatch, making the code much more readable and less error prone.
Otherwise, please could you move the above macro definitions to the top,
outside this function ?
What happens if the ETM doesn't have enough resources ? Do we fail the load
here ? Or do we fail the activation during enabling the ETM ? Or do we assume
all ETMs have the resources required for statically defined configs ?
quoted hunk
+ } while (0);
+ } else if ((offset >= TRCCNTRLDVRn(0)) &&
+ (offset <= TRCCNTVRn((ETMv4_MAX_CNTR - 1)))) {
+ /* 32 bit counter regs, 4 off (ETMv4_MAX_CNTR - 1) */
+ idx = (offset & GENMASK(3, 0)) / 4;
+ off_mask = offset & GENMASK(11, 4);
+ do {
+ CHECKREGIDX(TRCCNTRLDVRn(0), cntrldvr, idx, off_mask);
+ CHECKREGIDX(TRCCNTCTLRn(0), cntr_ctrl, idx, off_mask);
+ CHECKREGIDX(TRCCNTVRn(0), cntr_val, idx, off_mask);
+ } while (0);
+ }
+ return err;
+}
+
+/**
+ * etm4_cfg_load_feature - load a feature into a device instance.
+ *
+ * @csdev: An ETMv4 CoreSight device.
+ * @feat: The feature to be loaded.
+ *
+ * The function will load a feature instance into the device, checking that
+ * the register definitions are valid for the device.
+ *
+ * Parameter and register definitions will be converted into internal
+ * structures that are used to set the values in the driver when the
+ * feature is enabled for the device.
+ *
+ * The feature spinlock pointer is initialised to the same spinlock
+ * that the driver uses to protect the internal register values.
+ */
+static int etm4_cfg_load_feature(struct coresight_device *csdev,
+ struct cscfg_feature_csdev *feat)
+{
+ struct device *dev = csdev->dev.parent;
+ struct etmv4_drvdata *drvdata = dev_get_drvdata(dev);
+ const struct cscfg_feature_desc *feat_desc = feat->desc;
+ u32 offset;
+ int i = 0, err = 0;
+
+ /*
+ * essential we set the device spinlock - this is used in the generic
+ * programming routines when copying values into the drvdata structures
+ * via the pointers setup in etm4_cfg_map_reg_offset().
+ */
+ feat->csdev_spinlock = &drvdata->spinlock;
+
+ /* process the register descriptions */
+ for (i = 0; i < feat->nr_regs && !err; i++) {
+ offset = feat_desc->regs[i].offset;
+ err = etm4_cfg_map_reg_offset(drvdata, &feat->regs[i], offset);
+ }
+ return err;
+}
+
+/* match information when loading configurations */
+#define CS_CFG_ETM4_MATCH_FLAGS (CS_CFG_MATCH_CLASS_SRC_ALL | \
+ CS_CFG_MATCH_CLASS_SRC_ETM4)
+
+int etm4_cscfg_register(struct coresight_device *csdev, const char *dev_name)
+{
+ struct cscfg_match_desc cfg_info;
+ struct cscfg_csdev_feat_ops ops;
+
+ cfg_info.match_flags = CS_CFG_ETM4_MATCH_FLAGS;
+
+ ops.load_feat = &etm4_cfg_load_feature;
+
+ return cscfg_register_csdev(csdev, &cfg_info, &ops);
+}
Where are these used ? Probably better to move it to the patch
where they are actually used.
Suzuki
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
From: Mike Leach <hidden> Date: 2021-03-17 16:09:09
Hi Suzuki,
Realised I hadn't answered the question below...
On Fri, 5 Mar 2021 at 10:18, Suzuki K Poulose [off-list ref] wrote:
On 1/28/21 5:09 PM, Mike Leach wrote:
quoted
Adds in handlers to allow the ETMv4 to use the complex configuration
support. Features and configurations can be loaded and selected in the
device.
Signed-off-by: Mike Leach <redacted>
---
drivers/hwtracing/coresight/Makefile | 3 +-
.../hwtracing/coresight/coresight-etm4x-cfg.c | 184 ++++++++++++++++++
.../hwtracing/coresight/coresight-etm4x-cfg.h | 29 +++
.../coresight/coresight-etm4x-core.c | 38 +++-
.../coresight/coresight-etm4x-sysfs.c | 3 +
5 files changed, 254 insertions(+), 3 deletions(-)
create mode 100644 drivers/hwtracing/coresight/coresight-etm4x-cfg.c
create mode 100644 drivers/hwtracing/coresight/coresight-etm4x-cfg.h
I think we can live with switch-case, ignoring the Warnings generated by the
checkpatch, making the code much more readable and less error prone.
Otherwise, please could you move the above macro definitions to the top,
outside this function ?
What happens if the ETM doesn't have enough resources ? Do we fail the load
here ? Or do we fail the activation during enabling the ETM ? Or do we assume
all ETMs have the resources required for statically defined configs ?
Resource management will be in a follow-up set - dynamic load of
features and configurations will be gated on sufficient resources.
There are two stages where this can fail:-
1) a feature requires resources that the ETM does not have - this will
fail on load. Any dependent configuration will fail at this point
too. Where this is the result of dynamic load of a configuration and
features the load of that module will be failed.
2) a configuration uses more features than devices have total
resources for - this will fail on enable as a feature cannot be
programmed due to lack of resources.
For the built in config - for now we assume any platform has the
resources - in future we will fail the load of the feature, but not
the load of coresight itself.
Moving forwards I would expect that we will avoid having too many
built-in configs and push for all new ones to be a separate loadable
module as a minimum.
Thanks
Mike
quoted
+ } while (0);
+ } else if ((offset >= TRCCNTRLDVRn(0)) &&
+ (offset <= TRCCNTVRn((ETMv4_MAX_CNTR - 1)))) {
+ /* 32 bit counter regs, 4 off (ETMv4_MAX_CNTR - 1) */
+ idx = (offset & GENMASK(3, 0)) / 4;
+ off_mask = offset & GENMASK(11, 4);
+ do {
+ CHECKREGIDX(TRCCNTRLDVRn(0), cntrldvr, idx, off_mask);
+ CHECKREGIDX(TRCCNTCTLRn(0), cntr_ctrl, idx, off_mask);
+ CHECKREGIDX(TRCCNTVRn(0), cntr_val, idx, off_mask);
+ } while (0);
+ }
+ return err;
+}
+
+/**
+ * etm4_cfg_load_feature - load a feature into a device instance.
+ *
+ * @csdev: An ETMv4 CoreSight device.
+ * @feat: The feature to be loaded.
+ *
+ * The function will load a feature instance into the device, checking that
+ * the register definitions are valid for the device.
+ *
+ * Parameter and register definitions will be converted into internal
+ * structures that are used to set the values in the driver when the
+ * feature is enabled for the device.
+ *
+ * The feature spinlock pointer is initialised to the same spinlock
+ * that the driver uses to protect the internal register values.
+ */
+static int etm4_cfg_load_feature(struct coresight_device *csdev,
+ struct cscfg_feature_csdev *feat)
+{
+ struct device *dev = csdev->dev.parent;
+ struct etmv4_drvdata *drvdata = dev_get_drvdata(dev);
+ const struct cscfg_feature_desc *feat_desc = feat->desc;
+ u32 offset;
+ int i = 0, err = 0;
+
+ /*
+ * essential we set the device spinlock - this is used in the generic
+ * programming routines when copying values into the drvdata structures
+ * via the pointers setup in etm4_cfg_map_reg_offset().
+ */
+ feat->csdev_spinlock = &drvdata->spinlock;
+
+ /* process the register descriptions */
+ for (i = 0; i < feat->nr_regs && !err; i++) {
+ offset = feat_desc->regs[i].offset;
+ err = etm4_cfg_map_reg_offset(drvdata, &feat->regs[i], offset);
+ }
+ return err;
+}
+
+/* match information when loading configurations */
+#define CS_CFG_ETM4_MATCH_FLAGS (CS_CFG_MATCH_CLASS_SRC_ALL | \
+ CS_CFG_MATCH_CLASS_SRC_ETM4)
+
+int etm4_cscfg_register(struct coresight_device *csdev, const char *dev_name)
+{
+ struct cscfg_match_desc cfg_info;
+ struct cscfg_csdev_feat_ops ops;
+
+ cfg_info.match_flags = CS_CFG_ETM4_MATCH_FLAGS;
+
+ ops.load_feat = &etm4_cfg_load_feature;
+
+ return cscfg_register_csdev(csdev, &cfg_info, &ops);
+}
Where are these used ? Probably better to move it to the patch
where they are actually used.
Suzuki
--
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
From: Mike Leach <hidden> Date: 2021-01-28 17:47:01
Adds configfs subsystem and attributes to the configuration manager
to enable the listing of loaded configurations and features.
The default values of feature parameters can be accessed and altered
from these attributes to affect all installed devices using the feature.
Signed-off-by: Mike Leach <redacted>
---
drivers/hwtracing/coresight/Makefile | 3 +-
.../hwtracing/coresight/coresight-config.c | 1 +
.../coresight/coresight-syscfg-configfs.c | 399 ++++++++++++++++++
.../coresight/coresight-syscfg-configfs.h | 45 ++
.../hwtracing/coresight/coresight-syscfg.c | 77 ++++
.../hwtracing/coresight/coresight-syscfg.h | 7 +
6 files changed, 531 insertions(+), 1 deletion(-)
create mode 100644 drivers/hwtracing/coresight/coresight-syscfg-configfs.c
create mode 100644 drivers/hwtracing/coresight/coresight-syscfg-configfs.h
@@ -0,0 +1,399 @@+// SPDX-License-Identifier: GPL-2.0+/*+*Copyright(c)2020LinaroLimited,Allrightsreserved.+*Author:MikeLeach<mike.leach@linaro.org>+*/++#include<linux/configfs.h>++#include"coresight-syscfg-configfs.h"++/* create a default ci_type. */+staticinlinestructconfig_item_type*cscfg_create_ci_type(void)+{+structconfig_item_type*ci_type;++ci_type=devm_kzalloc(to_device_cscfg(),sizeof(*ci_type),GFP_KERNEL);+if(ci_type)+ci_type->ct_owner=THIS_MODULE;++returnci_type;+}++/* configurations sub-group */++/* attributes for the config view group */+staticssize_tcscfg_cfg_description_show(structconfig_item*item,char*page)+{+structcscfg_fs_config*fs_config=container_of(to_config_group(item),+structcscfg_fs_config,group);++returnscnprintf(page,PAGE_SIZE,"%s\n",fs_config->desc->brief);+}+CONFIGFS_ATTR_RO(cscfg_cfg_,description);++staticssize_tcscfg_cfg_feature_refs_show(structconfig_item*item,char*page)+{+structcscfg_fs_config*fs_config=container_of(to_config_group(item),+structcscfg_fs_config,group);+conststructcscfg_config_desc*desc=fs_config->desc;+ssize_tch_used=0;+inti;++if(desc->nr_refs){+for(i=0;i<desc->nr_refs;i++){+ch_used+=scnprintf(page+ch_used,PAGE_SIZE-ch_used,+"%s\n",desc->refs[i].name);+}+}+returnch_used;+}+CONFIGFS_ATTR_RO(cscfg_cfg_,feature_refs);++/* list preset values in order of features and params */+staticssize_tcscfg_cfg_values_show(structconfig_item*item,char*page)+{+conststructcscfg_feature_desc*feat;+conststructcscfg_config_desc*cfg;+structcscfg_fs_preset*fs_preset;+inti,j,val_idx,preset_idx;+ssize_tused=0;++fs_preset=container_of(to_config_group(item),structcscfg_fs_preset,group);+cfg=fs_preset->desc;++if(!cfg->nr_presets)+return0;++preset_idx=fs_preset->preset_num-1;++/* start index on the correct array line */+val_idx=cfg->nr_total_params*preset_idx;++/*+*Asetofpresetsisthesumofallparamsinusedfeatures,+*inorderofdeclarationoffeaturesandparamsinthefeatures+*/+for(i=0;i<cfg->nr_refs;i++){+feat=cscfg_get_named_feat_desc(cfg->refs[i].name);+for(j=0;j<feat->nr_params;j++){+used+=scnprintf(page+used,PAGE_SIZE-used,+"%s.%s = 0x%llx ",+feat->name,feat->params[j].name,+cfg->presets[val_idx++]);+}+}+used+=scnprintf(page+used,PAGE_SIZE-used,"\n");++returnused;+}+CONFIGFS_ATTR_RO(cscfg_cfg_,values);++staticstructconfigfs_attribute*cscfg_config_view_attrs[]={+&cscfg_cfg_attr_description,+&cscfg_cfg_attr_feature_refs,+NULL,+};++staticstructconfig_item_typecscfg_config_view_type={+.ct_owner=THIS_MODULE,+.ct_attrs=cscfg_config_view_attrs,+};++staticstructconfigfs_attribute*cscfg_config_preset_attrs[]={+&cscfg_cfg_attr_values,+NULL,+};++staticstructconfig_item_typecscfg_config_preset_type={+.ct_owner=THIS_MODULE,+.ct_attrs=cscfg_config_preset_attrs,+};+++staticintcscfg_add_preset_groups(structcscfg_fs_config*cfg_view)+{+intpreset_num;+structcscfg_fs_preset*cfg_preset;+structcscfg_config_desc*cfg_desc=cfg_view->desc;+charname[CONFIGFS_ITEM_NAME_LEN];++if(!cfg_desc->nr_presets)+return0;++for(preset_num=1;preset_num<=cfg_desc->nr_presets;preset_num++){+cfg_preset=devm_kzalloc(to_device_cscfg(),+sizeof(structcscfg_fs_config),GFP_KERNEL);++if(!cfg_preset)+return-ENOMEM;++snprintf(name,CONFIGFS_ITEM_NAME_LEN,"preset%d",preset_num);+cfg_preset->preset_num=preset_num;+cfg_preset->desc=cfg_view->desc;+config_group_init_type_name(&cfg_preset->group,name,+&cscfg_config_preset_type);+configfs_add_default_group(&cfg_preset->group,&cfg_view->group);+}+return0;+}++staticstructconfig_group*cscfg_create_config_group(structcscfg_config_desc*cfg_desc)+{+structcscfg_fs_config*cfg_view;+structdevice*dev=to_device_cscfg();+interr;++if(!dev)+returnERR_PTR(-EINVAL);++cfg_view=devm_kzalloc(dev,sizeof(structcscfg_fs_config),GFP_KERNEL);+if(!cfg_view)+returnERR_PTR(-ENOMEM);++cfg_view->desc=cfg_desc;+config_group_init_type_name(&cfg_view->group,cfg_desc->name,&cscfg_config_view_type);++/* add in a preset<n> dir for each preset */+err=cscfg_add_preset_groups(cfg_view);+if(err)+returnERR_PTR(err);++return&cfg_view->group;+}++/* attributes for features view */++staticssize_tcscfg_feat_description_show(structconfig_item*item,char*page)+{+structcscfg_fs_feature*fs_feat=container_of(to_config_group(item),+structcscfg_fs_feature,group);++returnscnprintf(page,PAGE_SIZE,"%s\n",fs_feat->desc->brief);+}+CONFIGFS_ATTR_RO(cscfg_feat_,description);++staticssize_tcscfg_feat_matches_show(structconfig_item*item,char*page)+{+structcscfg_fs_feature*fs_feat=container_of(to_config_group(item),+structcscfg_fs_feature,group);+u32match_flags=fs_feat->desc->match_flags;+intused=0;++if(match_flags&CS_CFG_MATCH_CLASS_SRC_ALL)+used=scnprintf(page,PAGE_SIZE,"SRC_ALL ");++if(match_flags&CS_CFG_MATCH_CLASS_SRC_ETM4)+used+=scnprintf(page+used,PAGE_SIZE-used,"SRC_ETMV4 ");++used+=scnprintf(page+used,PAGE_SIZE-used,"\n");+returnused;+}+CONFIGFS_ATTR_RO(cscfg_feat_,matches);++staticssize_tcscfg_feat_nr_params_show(structconfig_item*item,char*page)+{+structcscfg_fs_feature*fs_feat=container_of(to_config_group(item),+structcscfg_fs_feature,group);++returnscnprintf(page,PAGE_SIZE,"%d\n",fs_feat->desc->nr_params);+}+CONFIGFS_ATTR_RO(cscfg_feat_,nr_params);++/* base feature desc attrib structures */+staticstructconfigfs_attribute*cscfg_feature_view_attrs[]={+&cscfg_feat_attr_description,+&cscfg_feat_attr_matches,+&cscfg_feat_attr_nr_params,+NULL,+};++staticstructconfig_item_typecscfg_feature_view_type={+.ct_owner=THIS_MODULE,+.ct_attrs=cscfg_feature_view_attrs,+};++staticssize_tcscfg_param_value_show(structconfig_item*item,char*page)+{+structcscfg_fs_param*param_item=container_of(to_config_group(item),+structcscfg_fs_param,group);+intparam_idx=param_item->param_idx;+structcscfg_feature_desc*desc=param_item->desc;++returnscnprintf(page,PAGE_SIZE,"0x%llx\n",desc->params[param_idx].value);+}++staticssize_tcscfg_param_value_store(structconfig_item*item,+constchar*page,size_tsize)+{+structcscfg_fs_param*param_item=container_of(to_config_group(item),+structcscfg_fs_param,group);+structcscfg_feature_desc*desc=param_item->desc;+intparam_idx=param_item->param_idx;+u64val;+interr;++err=kstrtoull(page,0,&val);+if(!err)+err=cscfg_update_feat_param_val(desc,param_idx,val);++returnerr?err:size;+}+CONFIGFS_ATTR(cscfg_param_,value);++staticstructconfigfs_attribute*cscfg_param_view_attrs[]={+&cscfg_param_attr_value,+NULL,+};++staticstructconfig_item_typecscfg_param_view_type={+.ct_owner=THIS_MODULE,+.ct_attrs=cscfg_param_view_attrs,+};++/*+*configfshasfarlessfunctionalityprovidedtoaddattributesdynamicallythansysfs,+*andtheshowandstorefnspasstheenclosingconfig_itemsotheactualattributecannot+*bedetermined.Thereforeweaddeachitemasagroupdirectory,withavalueattribute.+*/+staticintcscfg_create_params_group_items(structcscfg_feature_desc*feat_desc,+structconfig_group*params_group)+{+structdevice*dev=to_device_cscfg();+structcscfg_fs_param*param_item;+inti;++/* parameter items - as groups with default_value attribute */+for(i=0;i<feat_desc->nr_params;i++){+param_item=devm_kzalloc(dev,sizeof(structcscfg_fs_param),GFP_KERNEL);+if(!param_item)+return-ENOMEM;+param_item->desc=feat_desc;+param_item->param_idx=i;+config_group_init_type_name(¶m_item->group,feat_desc->params[i].name,+&cscfg_param_view_type);+configfs_add_default_group(¶m_item->group,params_group);+}+return0;+}++staticstructconfig_group*cscfg_create_feature_group(structcscfg_feature_desc*feat_desc)+{+structcscfg_fs_feature*feat_view;+structconfig_item_type*params_group_type;+structconfig_group*params_group=NULL;+structdevice*dev=to_device_cscfg();+intitem_err;++if(!dev)+returnERR_PTR(-EINVAL);++feat_view=devm_kzalloc(dev,sizeof(structcscfg_fs_feature),GFP_KERNEL);+if(!feat_view)+returnERR_PTR(-ENOMEM);++if(feat_desc->nr_params){+params_group=devm_kzalloc(dev,sizeof(structconfig_group),GFP_KERNEL);+if(!params_group)+returnERR_PTR(-ENOMEM);++params_group_type=cscfg_create_ci_type();+if(!params_group_type)+returnERR_PTR(-ENOMEM);+}++feat_view->desc=feat_desc;+config_group_init_type_name(&feat_view->group,+feat_desc->name,+&cscfg_feature_view_type);+if(params_group){+config_group_init_type_name(params_group,"params",params_group_type);+configfs_add_default_group(params_group,&feat_view->group);+item_err=cscfg_create_params_group_items(feat_desc,params_group);+if(item_err)+returnERR_PTR(item_err);+}+return&feat_view->group;+}++staticstructconfig_item_typecscfg_configs_type={+.ct_owner=THIS_MODULE,+};++staticstructconfig_groupcscfg_configs_grp={+.cg_item={+.ci_namebuf="configurations",+.ci_type=&cscfg_configs_type,+},+};++/* add configuration to configurations group */+intcscfg_configfs_add_config(structcscfg_config_desc*cfg_desc)+{+structconfig_group*new_group;+interr;++new_group=cscfg_create_config_group(cfg_desc);+if(IS_ERR(new_group))+returnPTR_ERR(new_group);+err=configfs_register_group(&cscfg_configs_grp,new_group);+returnerr;+}++staticstructconfig_item_typecscfg_features_type={+.ct_owner=THIS_MODULE,+};++staticstructconfig_groupcscfg_features_grp={+.cg_item={+.ci_namebuf="features",+.ci_type=&cscfg_features_type,+},+};++/* add feature to features group */+intcscfg_configfs_add_feature(structcscfg_feature_desc*feat_desc)+{+structconfig_group*new_group;+interr;++new_group=cscfg_create_feature_group(feat_desc);+if(IS_ERR(new_group))+returnPTR_ERR(new_group);+err=configfs_register_group(&cscfg_features_grp,new_group);+returnerr;+}++intcscfg_configfs_init(structcscfg_manager*cscfg_mgr)+{+structconfigfs_subsystem*subsys;+structconfig_item_type*ci_type;++if(!cscfg_mgr)+return-EINVAL;++ci_type=cscfg_create_ci_type();+if(!ci_type)+return-ENOMEM;++subsys=&cscfg_mgr->cfgfs_subsys;+config_item_set_name(&subsys->su_group.cg_item,CSCFG_FS_SUBSYS_NAME);+subsys->su_group.cg_item.ci_type=ci_type;++config_group_init(&subsys->su_group);+mutex_init(&subsys->su_mutex);++/* Add default groups to subsystem */+config_group_init(&cscfg_configs_grp);+configfs_add_default_group(&cscfg_configs_grp,&subsys->su_group);++config_group_init(&cscfg_features_grp);+configfs_add_default_group(&cscfg_features_grp,&subsys->su_group);++returnconfigfs_register_subsystem(subsys);+}++voidcscfg_configfs_release(structcscfg_manager*cscfg_mgr)+{+configfs_unregister_subsystem(&cscfg_mgr->cfgfs_subsys);+}
@@ -302,6 +303,70 @@ static int cscfg_load_config(struct cscfg_config_desc *cfg_desc)return0;}+/* get a feature descriptor by name */+conststructcscfg_feature_desc*cscfg_get_named_feat_desc(constchar*name)+{+conststructcscfg_feature_desc*feat=NULL,*feat_item;++mutex_lock(&cscfg_mutex);++list_for_each_entry(feat_item,&cscfg_mgr->data.feat_desc_list,item){+if(strcmp(feat_item->name,name)==0){+feat=feat_item;+break;+}+}++mutex_unlock(&cscfg_mutex);+returnfeat;+}++staticstructcscfg_feature_csdev*+cscfg_csdev_get_feat_from_desc(structcoresight_device*csdev,+structcscfg_feature_desc*feat_desc)+{+structcscfg_feature_csdev*feat_csdev=NULL,*item;++list_for_each_entry(item,&csdev->feature_csdev_list,node){+if(item->desc==feat_desc){+feat_csdev=item;+break;+}+}+returnfeat_csdev;+}++intcscfg_update_feat_param_val(structcscfg_feature_desc*feat_desc,+intparam_idx,u64value)+{+interr=0;+structcscfg_feature_csdev*feat_csdev;+structcscfg_csdev_register*item;++mutex_lock(&cscfg_mutex);++/* check if any config active & return busy */+if(atomic_read(&cscfg_mgr->data.sys_active_cnt)){+err=-EBUSY;+gotounlock_exit;+}++/* set the value */+feat_desc->params[param_idx].value=value;++/* update loaded instances.*/+list_for_each_entry(item,&cscfg_mgr->data.csdev_desc_list,item){+feat_csdev=cscfg_csdev_get_feat_from_desc(item->csdev,feat_desc);+if(feat_csdev)+feat_csdev->params[param_idx].current_value=value;+}++unlock_exit:+mutex_unlock(&cscfg_mutex);+returnerr;+}++/**ExternalAPIfunctiontoloadfeatureandconfigsets.*Takea0terminatedarrayoffeaturedescriptorsand/orconfiguration
@@ -324,6 +389,7 @@ int cscfg_load_config_sets(struct cscfg_config_desc **cfg_descs,feat_descs[i]->name);gotodo_unlock;}+cscfg_configfs_add_feature(feat_descs[i]);i++;}}
@@ -338,6 +404,7 @@ int cscfg_load_config_sets(struct cscfg_config_desc **cfg_descs,cfg_descs[i]->name);gotodo_unlock;}+cscfg_configfs_add_config(cfg_descs[i]);i++;}}
@@ -613,6 +680,7 @@ struct device *to_device_cscfg(void)/* Must have a release function or the kernel will complain on module unload */voidcscfg_dev_release(structdevice*dev){+cscfg_configfs_release(cscfg_mgr);kfree(cscfg_mgr);cscfg_mgr=NULL;}
@@ -639,6 +707,7 @@ int cscfg_create_device(void)dev->init_name="system_cfg";err=device_register(dev);+if(err)cscfg_dev_release(dev);
@@ -668,6 +737,10 @@ int __init cscfg_init(void)if(err)returnerr;+err=cscfg_configfs_init(cscfg_mgr);+if(err)+gotoexit_dev_clear;+INIT_LIST_HEAD(&cscfg_mgr->data.csdev_desc_list);INIT_LIST_HEAD(&cscfg_mgr->data.feat_desc_list);INIT_LIST_HEAD(&cscfg_mgr->data.config_desc_list);
@@ -676,6 +749,10 @@ int __init cscfg_init(void)dev_info(to_device_cscfg(),"CoreSight Configuration manager initialised");return0;++exit_dev_clear:+cscfg_clear_device();+returnerr;}void__exitcscfg_exit(void)
@@ -71,10 +76,12 @@ void cscfg_csdev_disable_active_config(struct coresight_device *csdev);**@dev:Thedevice.*@data:TheAPIdata.+*@cfgfs_subsys:configfssubsystemusedtomanageconfigurations.*/structcscfg_manager{structdevicedev;structcscfg_api_datadata;+structconfigfs_subsystemcfgfs_subsys;};/* get reference to dev in cscfg_manager */
--
2.17.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
On Thu, Jan 28, 2021 at 05:09:35PM +0000, Mike Leach wrote:
quoted hunk
Adds configfs subsystem and attributes to the configuration manager
to enable the listing of loaded configurations and features.
The default values of feature parameters can be accessed and altered
from these attributes to affect all installed devices using the feature.
Signed-off-by: Mike Leach <redacted>
---
drivers/hwtracing/coresight/Makefile | 3 +-
.../hwtracing/coresight/coresight-config.c | 1 +
.../coresight/coresight-syscfg-configfs.c | 399 ++++++++++++++++++
.../coresight/coresight-syscfg-configfs.h | 45 ++
.../hwtracing/coresight/coresight-syscfg.c | 77 ++++
.../hwtracing/coresight/coresight-syscfg.h | 7 +
6 files changed, 531 insertions(+), 1 deletion(-)
create mode 100644 drivers/hwtracing/coresight/coresight-syscfg-configfs.c
create mode 100644 drivers/hwtracing/coresight/coresight-syscfg-configfs.h
@@ -0,0 +1,399 @@+// SPDX-License-Identifier: GPL-2.0+/*+*Copyright(c)2020LinaroLimited,Allrightsreserved.+*Author:MikeLeach<mike.leach@linaro.org>+*/++#include<linux/configfs.h>++#include"coresight-syscfg-configfs.h"++/* create a default ci_type. */+staticinlinestructconfig_item_type*cscfg_create_ci_type(void)+{+structconfig_item_type*ci_type;++ci_type=devm_kzalloc(to_device_cscfg(),sizeof(*ci_type),GFP_KERNEL);+if(ci_type)+ci_type->ct_owner=THIS_MODULE;++returnci_type;+}++/* configurations sub-group */++/* attributes for the config view group */+staticssize_tcscfg_cfg_description_show(structconfig_item*item,char*page)+{+structcscfg_fs_config*fs_config=container_of(to_config_group(item),+structcscfg_fs_config,group);++returnscnprintf(page,PAGE_SIZE,"%s\n",fs_config->desc->brief);+}+CONFIGFS_ATTR_RO(cscfg_cfg_,description);++staticssize_tcscfg_cfg_feature_refs_show(structconfig_item*item,char*page)+{+structcscfg_fs_config*fs_config=container_of(to_config_group(item),+structcscfg_fs_config,group);+conststructcscfg_config_desc*desc=fs_config->desc;+ssize_tch_used=0;+inti;++if(desc->nr_refs){+for(i=0;i<desc->nr_refs;i++){+ch_used+=scnprintf(page+ch_used,PAGE_SIZE-ch_used,+"%s\n",desc->refs[i].name);+}+}+returnch_used;+}+CONFIGFS_ATTR_RO(cscfg_cfg_,feature_refs);++/* list preset values in order of features and params */+staticssize_tcscfg_cfg_values_show(structconfig_item*item,char*page)+{+conststructcscfg_feature_desc*feat;+conststructcscfg_config_desc*cfg;+structcscfg_fs_preset*fs_preset;+inti,j,val_idx,preset_idx;+ssize_tused=0;++fs_preset=container_of(to_config_group(item),structcscfg_fs_preset,group);+cfg=fs_preset->desc;++if(!cfg->nr_presets)+return0;++preset_idx=fs_preset->preset_num-1;++/* start index on the correct array line */+val_idx=cfg->nr_total_params*preset_idx;++/*+*Asetofpresetsisthesumofallparamsinusedfeatures,+*inorderofdeclarationoffeaturesandparamsinthefeatures+*/+for(i=0;i<cfg->nr_refs;i++){+feat=cscfg_get_named_feat_desc(cfg->refs[i].name);+for(j=0;j<feat->nr_params;j++){+used+=scnprintf(page+used,PAGE_SIZE-used,+"%s.%s = 0x%llx ",+feat->name,feat->params[j].name,+cfg->presets[val_idx++]);+}+}+used+=scnprintf(page+used,PAGE_SIZE-used,"\n");++returnused;+}+CONFIGFS_ATTR_RO(cscfg_cfg_,values);++staticstructconfigfs_attribute*cscfg_config_view_attrs[]={+&cscfg_cfg_attr_description,+&cscfg_cfg_attr_feature_refs,+NULL,+};++staticstructconfig_item_typecscfg_config_view_type={+.ct_owner=THIS_MODULE,+.ct_attrs=cscfg_config_view_attrs,+};++staticstructconfigfs_attribute*cscfg_config_preset_attrs[]={+&cscfg_cfg_attr_values,+NULL,+};++staticstructconfig_item_typecscfg_config_preset_type={+.ct_owner=THIS_MODULE,+.ct_attrs=cscfg_config_preset_attrs,+};++
@@ -302,6 +303,70 @@ static int cscfg_load_config(struct cscfg_config_desc *cfg_desc)return0;}+/* get a feature descriptor by name */+conststructcscfg_feature_desc*cscfg_get_named_feat_desc(constchar*name)+{+conststructcscfg_feature_desc*feat=NULL,*feat_item;++mutex_lock(&cscfg_mutex);++list_for_each_entry(feat_item,&cscfg_mgr->data.feat_desc_list,item){+if(strcmp(feat_item->name,name)==0){+feat=feat_item;+break;+}+}++mutex_unlock(&cscfg_mutex);+returnfeat;+}++staticstructcscfg_feature_csdev*+cscfg_csdev_get_feat_from_desc(structcoresight_device*csdev,+structcscfg_feature_desc*feat_desc)+{+structcscfg_feature_csdev*feat_csdev=NULL,*item;++list_for_each_entry(item,&csdev->feature_csdev_list,node){+if(item->desc==feat_desc){+feat_csdev=item;+break;+}+}+returnfeat_csdev;+}++intcscfg_update_feat_param_val(structcscfg_feature_desc*feat_desc,+intparam_idx,u64value)+{+interr=0;+structcscfg_feature_csdev*feat_csdev;+structcscfg_csdev_register*item;++mutex_lock(&cscfg_mutex);++/* check if any config active & return busy */+if(atomic_read(&cscfg_mgr->data.sys_active_cnt)){+err=-EBUSY;+gotounlock_exit;+}++/* set the value */+feat_desc->params[param_idx].value=value;++/* update loaded instances.*/+list_for_each_entry(item,&cscfg_mgr->data.csdev_desc_list,item){+feat_csdev=cscfg_csdev_get_feat_from_desc(item->csdev,feat_desc);+if(feat_csdev)+feat_csdev->params[param_idx].current_value=value;+}++unlock_exit:+mutex_unlock(&cscfg_mutex);+returnerr;+}++
Extra line
quoted hunk
/*
* External API function to load feature and config sets.
* Take a 0 terminated array of feature descriptors and/or configuration
@@ -613,6 +680,7 @@ struct device *to_device_cscfg(void) /* Must have a release function or the kernel will complain on module unload */ void cscfg_dev_release(struct device *dev) {+ cscfg_configfs_release(cscfg_mgr); kfree(cscfg_mgr); cscfg_mgr = NULL; }
Extra line
I have run out of time for this patchset. Please spin off another revision and
we'll go from there.
The core of the feature works and I think we should move forward with it.
Thanks,
Mathieu
quoted hunk
if (err)
cscfg_dev_release(dev);
@@ -668,6 +737,10 @@ int __init cscfg_init(void) if (err) return err;+ err = cscfg_configfs_init(cscfg_mgr);+ if (err)+ goto exit_dev_clear;+ INIT_LIST_HEAD(&cscfg_mgr->data.csdev_desc_list); INIT_LIST_HEAD(&cscfg_mgr->data.feat_desc_list); INIT_LIST_HEAD(&cscfg_mgr->data.config_desc_list);
@@ -71,10 +76,12 @@ void cscfg_csdev_disable_active_config(struct coresight_device *csdev);**@dev:Thedevice.*@data:TheAPIdata.+*@cfgfs_subsys:configfssubsystemusedtomanageconfigurations.*/structcscfg_manager{structdevicedev;structcscfg_api_datadata;+structconfigfs_subsystemcfgfs_subsys;};/* get reference to dev in cscfg_manager */
On Sun, Feb 28, 2021 at 05:02:28PM -0700, Mathieu Poirier wrote:
On Thu, Jan 28, 2021 at 05:09:35PM +0000, Mike Leach wrote:
quoted
Adds configfs subsystem and attributes to the configuration manager
to enable the listing of loaded configurations and features.
The default values of feature parameters can be accessed and altered
from these attributes to affect all installed devices using the feature.
Signed-off-by: Mike Leach <redacted>
I get the following warning when applying this patch:
Applying: coresight: syscfg: Add initial configfs support
.git/rebase-apply/patch:34: new blank line at EOF.
+
warning: 1 line adds whitespace errors.
Please address.
@@ -0,0 +1,399 @@+// SPDX-License-Identifier: GPL-2.0+/*+*Copyright(c)2020LinaroLimited,Allrightsreserved.+*Author:MikeLeach<mike.leach@linaro.org>+*/++#include<linux/configfs.h>++#include"coresight-syscfg-configfs.h"++/* create a default ci_type. */+staticinlinestructconfig_item_type*cscfg_create_ci_type(void)+{+structconfig_item_type*ci_type;++ci_type=devm_kzalloc(to_device_cscfg(),sizeof(*ci_type),GFP_KERNEL);+if(ci_type)+ci_type->ct_owner=THIS_MODULE;++returnci_type;+}++/* configurations sub-group */++/* attributes for the config view group */+staticssize_tcscfg_cfg_description_show(structconfig_item*item,char*page)+{+structcscfg_fs_config*fs_config=container_of(to_config_group(item),+structcscfg_fs_config,group);++returnscnprintf(page,PAGE_SIZE,"%s\n",fs_config->desc->brief);+}+CONFIGFS_ATTR_RO(cscfg_cfg_,description);++staticssize_tcscfg_cfg_feature_refs_show(structconfig_item*item,char*page)+{+structcscfg_fs_config*fs_config=container_of(to_config_group(item),+structcscfg_fs_config,group);+conststructcscfg_config_desc*desc=fs_config->desc;+ssize_tch_used=0;+inti;++if(desc->nr_refs){+for(i=0;i<desc->nr_refs;i++){+ch_used+=scnprintf(page+ch_used,PAGE_SIZE-ch_used,+"%s\n",desc->refs[i].name);+}+}+returnch_used;+}+CONFIGFS_ATTR_RO(cscfg_cfg_,feature_refs);++/* list preset values in order of features and params */+staticssize_tcscfg_cfg_values_show(structconfig_item*item,char*page)+{+conststructcscfg_feature_desc*feat;+conststructcscfg_config_desc*cfg;+structcscfg_fs_preset*fs_preset;+inti,j,val_idx,preset_idx;+ssize_tused=0;++fs_preset=container_of(to_config_group(item),structcscfg_fs_preset,group);+cfg=fs_preset->desc;++if(!cfg->nr_presets)+return0;++preset_idx=fs_preset->preset_num-1;++/* start index on the correct array line */+val_idx=cfg->nr_total_params*preset_idx;++/*+*Asetofpresetsisthesumofallparamsinusedfeatures,+*inorderofdeclarationoffeaturesandparamsinthefeatures+*/+for(i=0;i<cfg->nr_refs;i++){+feat=cscfg_get_named_feat_desc(cfg->refs[i].name);+for(j=0;j<feat->nr_params;j++){+used+=scnprintf(page+used,PAGE_SIZE-used,+"%s.%s = 0x%llx ",+feat->name,feat->params[j].name,+cfg->presets[val_idx++]);+}+}+used+=scnprintf(page+used,PAGE_SIZE-used,"\n");++returnused;+}+CONFIGFS_ATTR_RO(cscfg_cfg_,values);++staticstructconfigfs_attribute*cscfg_config_view_attrs[]={+&cscfg_cfg_attr_description,+&cscfg_cfg_attr_feature_refs,+NULL,+};++staticstructconfig_item_typecscfg_config_view_type={+.ct_owner=THIS_MODULE,+.ct_attrs=cscfg_config_view_attrs,+};++staticstructconfigfs_attribute*cscfg_config_preset_attrs[]={+&cscfg_cfg_attr_values,+NULL,+};++staticstructconfig_item_typecscfg_config_preset_type={+.ct_owner=THIS_MODULE,+.ct_attrs=cscfg_config_preset_attrs,+};++
@@ -302,6 +303,70 @@ static int cscfg_load_config(struct cscfg_config_desc *cfg_desc)return0;}+/* get a feature descriptor by name */+conststructcscfg_feature_desc*cscfg_get_named_feat_desc(constchar*name)+{+conststructcscfg_feature_desc*feat=NULL,*feat_item;++mutex_lock(&cscfg_mutex);++list_for_each_entry(feat_item,&cscfg_mgr->data.feat_desc_list,item){+if(strcmp(feat_item->name,name)==0){+feat=feat_item;+break;+}+}++mutex_unlock(&cscfg_mutex);+returnfeat;+}++staticstructcscfg_feature_csdev*+cscfg_csdev_get_feat_from_desc(structcoresight_device*csdev,+structcscfg_feature_desc*feat_desc)+{+structcscfg_feature_csdev*feat_csdev=NULL,*item;++list_for_each_entry(item,&csdev->feature_csdev_list,node){+if(item->desc==feat_desc){+feat_csdev=item;+break;+}+}+returnfeat_csdev;+}++intcscfg_update_feat_param_val(structcscfg_feature_desc*feat_desc,+intparam_idx,u64value)+{+interr=0;+structcscfg_feature_csdev*feat_csdev;+structcscfg_csdev_register*item;++mutex_lock(&cscfg_mutex);++/* check if any config active & return busy */+if(atomic_read(&cscfg_mgr->data.sys_active_cnt)){+err=-EBUSY;+gotounlock_exit;+}++/* set the value */+feat_desc->params[param_idx].value=value;++/* update loaded instances.*/+list_for_each_entry(item,&cscfg_mgr->data.csdev_desc_list,item){+feat_csdev=cscfg_csdev_get_feat_from_desc(item->csdev,feat_desc);+if(feat_csdev)+feat_csdev->params[param_idx].current_value=value;+}++unlock_exit:+mutex_unlock(&cscfg_mutex);+returnerr;+}++
Extra line
quoted
/*
* External API function to load feature and config sets.
* Take a 0 terminated array of feature descriptors and/or configuration
@@ -613,6 +680,7 @@ struct device *to_device_cscfg(void) /* Must have a release function or the kernel will complain on module unload */ void cscfg_dev_release(struct device *dev) {+ cscfg_configfs_release(cscfg_mgr); kfree(cscfg_mgr); cscfg_mgr = NULL; }
Extra line
I have run out of time for this patchset. Please spin off another revision and
we'll go from there.
The core of the feature works and I think we should move forward with it.
Thanks,
Mathieu
quoted
if (err)
cscfg_dev_release(dev);
@@ -668,6 +737,10 @@ int __init cscfg_init(void) if (err) return err;+ err = cscfg_configfs_init(cscfg_mgr);+ if (err)+ goto exit_dev_clear;+ INIT_LIST_HEAD(&cscfg_mgr->data.csdev_desc_list); INIT_LIST_HEAD(&cscfg_mgr->data.feat_desc_list); INIT_LIST_HEAD(&cscfg_mgr->data.config_desc_list);
@@ -71,10 +76,12 @@ void cscfg_csdev_disable_active_config(struct coresight_device *csdev);**@dev:Thedevice.*@data:TheAPIdata.+*@cfgfs_subsys:configfssubsystemusedtomanageconfigurations.*/structcscfg_manager{structdevicedev;structcscfg_api_datadata;+structconfigfs_subsystemcfgfs_subsys;};/* get reference to dev in cscfg_manager */
@@ -178,6 +178,10 @@ static void free_event_data(struct work_struct *work)/* Free the sink buffers, if there are any */free_sink_buffer(event_data);+/* clear any configuration we were using */+if(event_data->config_id_hash)+cscfg_deactivate_config(event_data->config_id_hash);+for_each_cpu(cpu,mask){structlist_head**ppath;
@@ -178,6 +178,10 @@ static void free_event_data(struct work_struct *work)/* Free the sink buffers, if there are any */free_sink_buffer(event_data);+/* clear any configuration we were using */+if(event_data->config_id_hash)+cscfg_deactivate_config(event_data->config_id_hash);+for_each_cpu(cpu,mask){structlist_head**ppath;
@@ -178,6 +178,10 @@ static void free_event_data(struct work_struct *work)/* Free the sink buffers, if there are any */free_sink_buffer(event_data);+/* clear any configuration we were using */+if(event_data->config_id_hash)+cscfg_deactivate_config(event_data->config_id_hash);+for_each_cpu(cpu,mask){structlist_head**ppath;
Please align this with the naming convention you will be using above and
throughout.
More comments tomorrow.
Thanks,
Mathieu
quoted
struct list_head * __percpu *path;
};
--
2.17.1
Thanks
Mike
--
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
@@ -0,0 +1,244 @@+.. SPDX-License-Identifier: GPL-2.0++======================================+CoreSight System Configuration Manager+======================================++:Author: Mike Leach <mike.leach@linaro.org>+:Date: October 2020++Introduction+============++The CoreSight System Configuration manager is an API that allows the+programming of the CoreSight system with pre-defined configurations that+can then be easily enabled from sysfs or perf.++Many CoreSight components can be programmed in complex ways - especially ETMs.+In addition, components can interact across the CoreSight system, often via+the cross trigger components such as CTI and CTM. These system settings can+be defined and enabled as named configurations.+++Basic Concepts+==============++This section introduces the basic concepts of a CoreSight system configuration.+++Features+--------++A feature is a named set of programming for a CoreSight device. The programming+is device dependent, and can be defined in terms of absolute register values,+resource usage and parameter values.++The feature is defined using a descriptor. This descriptor is used to load onto+a matching device, either when the feature is loaded into the system, or when the+CoreSight device is registered with the configuration manager.++The load process involves interpreting the descriptor into a set of register+accesses in the driver - the resource usage and parameter descriptions+translated into appropriate register accesses. This interpretation makes it easy+and efficient for the feature to be programmed onto the device when required.++The feature will not be active on the device until the feature is enabled, and+the device itself is enabled. When the device is enabled then enabled features+will be programmed into the device hardware.++A feature is enabled as part of a configuration being enabled on the system.+++Parameter Value+~~~~~~~~~~~~~~~++A parameter value is a named value that may be set by the user prior to the+feature being enabled that can adjust the behaviour of the operation programmed+by the feature.++For example, this could be a count value in a programmed operation that repeats+at a given rate. When the feature is enabled then the current value of the+parameter is used in programming the device.++The feature descriptor defines a default value for a parameter, which is used+if the user does not supply a new value.++Users can update parameter values using the configfs API for the CoreSight+system - which is described below.++The current value of the parameter is loaded into the device when the feature+is enabled on that device.+++Configurations+--------------++A configuration defines a set of features that are to be used in a trace+session where the configuration is selected. For any trace session only one+configuration may be selected.++The features defined may be on any type of device that is registered+to support system configuration. A configuration may select features to be+enabled on a class of devices - i.e. any ETMv4, or specific devices, e.g. a+specific CTI on the system.++As with the feature, a descriptor is used to define the configuration.+This will define the features that must be enabled as part of the configuration+as well as any preset values that can be used to override default parameter+values.+++Preset Values+~~~~~~~~~~~~~++Preset values are easily selectable sets of parameter values for the features+that the configuration uses. The number of values in a single preset set, equals+the sum of parameter values in the features used by the configuration.++e.g. a configuration consists of 3 features, one has 2 parameters, one has+a single parameter, and another has no parameters. A single preset set will+therefore have 3 values.++Presets are optionally defined by the configuration, up to 15 can be defined.+If no preset is selected, then the parameter values defined in the feature+are used as normal.+++Operation+~~~~~~~~~++The following steps take place in the operation of a configuration.++1) In this example, the configuration is 'autofdo', which has an+ associated feature 'strobing' that works on ETMv4 CoreSight Devices.++2) The configuration is enabled. For example 'perf' may select the+ configuration as part of its command line::++ perf record -e cs_etm/autofdo/ myapp++ which will enable the 'autofdo' configuration.++3) perf starts tracing on the system. As each ETMv4 that perf uses for+ trace is enabled, the configuration manager will check if the ETMv4+ has a feature that relates to the currently active configuration.+ In this case 'strobing' is enabled & programmed into the ETMv4.++4) When the ETMv4 is disabled, any registers marked as needing to be+ saved will be read back.++5) At the end of the perf session, the configuration will be disabled.+++Viewing Configurations and Features+===================================++The set of configurations and features that are currently loaded into the+system can be viewed using the configfs API.++Mount configfs as normal and the 'coresight-syscfg' subsystem will appear::++ $ ls /config+ coresight-syscfg stp-policy++This has two sub-directories::++ $ cd coresight-syscfg/+ $ ls+ configurations features++The system has the configuration 'autofdo' built in. It may be examined as+follows::++ $ cd configurations/+ $ ls+ autofdo+ $ cd autofdo/+ $ ls+ description preset1 preset3 preset5 preset7 preset9+ feature_refs preset2 preset4 preset6 preset8+ $ cat description+ Setup ETMs with strobing for autofdo+ $ cat feature_refs+ strobing++Each preset declared has a preset<n> subdirectory declared. The values for+the preset can be examined::++ $ cat preset1/values+ strobing.window = 0x1388 strobing.period = 0x2+ $ cat preset2/values+ strobing.window = 0x1388 strobing.period = 0x4++The features referenced by the configuration can be examined in the features+directory::++ $ cd ../../features/strobing/+ $ ls+ description matches nr_params params+ $ cat description+ Generate periodic trace capture windows.+ parameter 'window': a number of CPU cycles (W)+ parameter 'period': trace enabled for W cycles every period x W cycles+ $ cat matches+ SRC_ETMV4+ $ cat nr_params+ 2++Move to the params directory to examine and adjust parameters::++ cd params+ $ ls+ period window+ $ cd period+ $ ls+ value+ $ cat value+ 0x2710+ # echo 15000 > value+ # cat value+ 0x3a98++Parameters adjusted in this way are reflected in all device instances that have+loaded the feature.+++Using Configurations in perf+============================++The configurations loaded into the CoreSight configuration management are+also declared in the perf 'cs_etm' event infrastructure so that they can+be selected when running trace under perf::++ $ ls /sys/devices/cs_etm+ configurations format perf_event_mux_interval_ms sinks type+ events nr_addr_filters power++Key directories here are 'configurations' - which lists the loaded+configurations, and 'events' - a generic perf directory which allows+selection on the perf command line.::++ $ ls configurations/+ autofdo+ $ cat configurations/autofdo+ 0xa7c3dddd++As with the sinks entries, this provides a hash of the configuration name.+The entry in the 'events' directory uses perfs built in syntax generator+to substitute the syntax for the name when evaluating the command::++ $ ls events/+ autofdo+ $ cat events/autofdo+ configid=0xa7c3dddd++The 'autofdo' configuration may be selected on the perf command line::++ $ perf record -e cs_etm/autofdo/u --per-thread <application>++A preset to override the current parameter values can also be selected::++ $ perf record -e cs_etm/autofdo,preset=1/u --per-thread <application>++When configurations are selected in this way, then the trace sink used is+automatically selected.
@@ -587,6 +587,20 @@ A separate documentation file is provided to explain the use of these devices. (:doc:`coresight-ect`) [#fourth]_.+CoreSight System Configuration+------------------------------++CoreSight components can be complex devices with many programming options.+Furthermore, components can be programmed to interact with each other across the+complete system.++A CoreSight System Configuration manager is provided to allow these complex programming+configurations to be selected and used easily from perf and sysfs.++See the separate document for further information.+(:doc:`coresight-config`) [#fifth]_.++..[#first] Documentation/ABI/testing/sysfs-bus-coresight-devices-stm..[#second] Documentation/trace/stm.rst
@@ -594,3 +608,5 @@ A separate documentation file is provided to explain the use of these devices...[#third] https://github.com/Linaro/perf-opencsd..[#fourth] Documentation/trace/coresight/coresight-ect.rst++..[#fifth] Documentation/trace/coresight/coresight-config.rst
--
2.17.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Good day,
I have started to review this set and as usual comments will come over several
days.
On Thu, Jan 28, 2021 at 05:09:36PM +0000, Mike Leach wrote:
Adds documentation for the CoreSight System configuration manager.
Signed-off-by: Mike Leach <redacted>
---
.../trace/coresight/coresight-config.rst | 244 ++++++++++++++++++
Documentation/trace/coresight/coresight.rst | 16 ++
2 files changed, 260 insertions(+)
create mode 100644 Documentation/trace/coresight/coresight-config.rst
At this time the content of the patch and how things have been laid out in
configfs look good to me. Things can still change at some point in the future
but for now:
Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
@@ -0,0 +1,244 @@+.. SPDX-License-Identifier: GPL-2.0++======================================+CoreSight System Configuration Manager+======================================++:Author: Mike Leach <mike.leach@linaro.org>+:Date: October 2020++Introduction+============++The CoreSight System Configuration manager is an API that allows the+programming of the CoreSight system with pre-defined configurations that+can then be easily enabled from sysfs or perf.++Many CoreSight components can be programmed in complex ways - especially ETMs.+In addition, components can interact across the CoreSight system, often via+the cross trigger components such as CTI and CTM. These system settings can+be defined and enabled as named configurations.+++Basic Concepts+==============++This section introduces the basic concepts of a CoreSight system configuration.+++Features+--------++A feature is a named set of programming for a CoreSight device. The programming+is device dependent, and can be defined in terms of absolute register values,+resource usage and parameter values.++The feature is defined using a descriptor. This descriptor is used to load onto+a matching device, either when the feature is loaded into the system, or when the+CoreSight device is registered with the configuration manager.++The load process involves interpreting the descriptor into a set of register+accesses in the driver - the resource usage and parameter descriptions+translated into appropriate register accesses. This interpretation makes it easy+and efficient for the feature to be programmed onto the device when required.++The feature will not be active on the device until the feature is enabled, and+the device itself is enabled. When the device is enabled then enabled features+will be programmed into the device hardware.++A feature is enabled as part of a configuration being enabled on the system.+++Parameter Value+~~~~~~~~~~~~~~~++A parameter value is a named value that may be set by the user prior to the+feature being enabled that can adjust the behaviour of the operation programmed+by the feature.++For example, this could be a count value in a programmed operation that repeats+at a given rate. When the feature is enabled then the current value of the+parameter is used in programming the device.++The feature descriptor defines a default value for a parameter, which is used+if the user does not supply a new value.++Users can update parameter values using the configfs API for the CoreSight+system - which is described below.++The current value of the parameter is loaded into the device when the feature+is enabled on that device.+++Configurations+--------------++A configuration defines a set of features that are to be used in a trace+session where the configuration is selected. For any trace session only one+configuration may be selected.++The features defined may be on any type of device that is registered+to support system configuration. A configuration may select features to be+enabled on a class of devices - i.e. any ETMv4, or specific devices, e.g. a+specific CTI on the system.++As with the feature, a descriptor is used to define the configuration.+This will define the features that must be enabled as part of the configuration+as well as any preset values that can be used to override default parameter+values.+++Preset Values+~~~~~~~~~~~~~++Preset values are easily selectable sets of parameter values for the features+that the configuration uses. The number of values in a single preset set, equals+the sum of parameter values in the features used by the configuration.++e.g. a configuration consists of 3 features, one has 2 parameters, one has+a single parameter, and another has no parameters. A single preset set will+therefore have 3 values.++Presets are optionally defined by the configuration, up to 15 can be defined.+If no preset is selected, then the parameter values defined in the feature+are used as normal.+++Operation+~~~~~~~~~++The following steps take place in the operation of a configuration.++1) In this example, the configuration is 'autofdo', which has an+ associated feature 'strobing' that works on ETMv4 CoreSight Devices.++2) The configuration is enabled. For example 'perf' may select the+ configuration as part of its command line::++ perf record -e cs_etm/autofdo/ myapp++ which will enable the 'autofdo' configuration.++3) perf starts tracing on the system. As each ETMv4 that perf uses for+ trace is enabled, the configuration manager will check if the ETMv4+ has a feature that relates to the currently active configuration.+ In this case 'strobing' is enabled & programmed into the ETMv4.++4) When the ETMv4 is disabled, any registers marked as needing to be+ saved will be read back.++5) At the end of the perf session, the configuration will be disabled.+++Viewing Configurations and Features+===================================++The set of configurations and features that are currently loaded into the+system can be viewed using the configfs API.++Mount configfs as normal and the 'coresight-syscfg' subsystem will appear::++ $ ls /config+ coresight-syscfg stp-policy++This has two sub-directories::++ $ cd coresight-syscfg/+ $ ls+ configurations features++The system has the configuration 'autofdo' built in. It may be examined as+follows::++ $ cd configurations/+ $ ls+ autofdo+ $ cd autofdo/+ $ ls+ description preset1 preset3 preset5 preset7 preset9+ feature_refs preset2 preset4 preset6 preset8+ $ cat description+ Setup ETMs with strobing for autofdo+ $ cat feature_refs+ strobing++Each preset declared has a preset<n> subdirectory declared. The values for+the preset can be examined::++ $ cat preset1/values+ strobing.window = 0x1388 strobing.period = 0x2+ $ cat preset2/values+ strobing.window = 0x1388 strobing.period = 0x4++The features referenced by the configuration can be examined in the features+directory::++ $ cd ../../features/strobing/+ $ ls+ description matches nr_params params+ $ cat description+ Generate periodic trace capture windows.+ parameter 'window': a number of CPU cycles (W)+ parameter 'period': trace enabled for W cycles every period x W cycles+ $ cat matches+ SRC_ETMV4+ $ cat nr_params+ 2++Move to the params directory to examine and adjust parameters::++ cd params+ $ ls+ period window+ $ cd period+ $ ls+ value+ $ cat value+ 0x2710+ # echo 15000 > value+ # cat value+ 0x3a98++Parameters adjusted in this way are reflected in all device instances that have+loaded the feature.+++Using Configurations in perf+============================++The configurations loaded into the CoreSight configuration management are+also declared in the perf 'cs_etm' event infrastructure so that they can+be selected when running trace under perf::++ $ ls /sys/devices/cs_etm+ configurations format perf_event_mux_interval_ms sinks type+ events nr_addr_filters power++Key directories here are 'configurations' - which lists the loaded+configurations, and 'events' - a generic perf directory which allows+selection on the perf command line.::++ $ ls configurations/+ autofdo+ $ cat configurations/autofdo+ 0xa7c3dddd++As with the sinks entries, this provides a hash of the configuration name.+The entry in the 'events' directory uses perfs built in syntax generator+to substitute the syntax for the name when evaluating the command::++ $ ls events/+ autofdo+ $ cat events/autofdo+ configid=0xa7c3dddd++The 'autofdo' configuration may be selected on the perf command line::++ $ perf record -e cs_etm/autofdo/u --per-thread <application>++A preset to override the current parameter values can also be selected::++ $ perf record -e cs_etm/autofdo,preset=1/u --per-thread <application>++When configurations are selected in this way, then the trace sink used is+automatically selected.
@@ -587,6 +587,20 @@ A separate documentation file is provided to explain the use of these devices. (:doc:`coresight-ect`) [#fourth]_.+CoreSight System Configuration+------------------------------++CoreSight components can be complex devices with many programming options.+Furthermore, components can be programmed to interact with each other across the+complete system.++A CoreSight System Configuration manager is provided to allow these complex programming+configurations to be selected and used easily from perf and sysfs.++See the separate document for further information.+(:doc:`coresight-config`) [#fifth]_.++..[#first] Documentation/ABI/testing/sysfs-bus-coresight-devices-stm..[#second] Documentation/trace/stm.rst
@@ -594,3 +608,5 @@ A separate documentation file is provided to explain the use of these devices...[#third] https://github.com/Linaro/perf-opencsd..[#fourth] Documentation/trace/coresight/coresight-ect.rst++..[#fifth] Documentation/trace/coresight/coresight-config.rst
From: Mike Leach <hidden> Date: 2021-01-28 17:48:19
Preload set of configurations.
This patch creates a small set of preloaded configurations and features
that are available immediately after coresight has been initialised.
The current set provides a strobing feature for ETMv4, that creates a
periodic sampling of trace by switching trace generation on and off
using counters in the ETM.
A configuration called "autofdo" is also provided that uses the 'strobing'
feature and provides a couple of preset values, selectable on the perf
command line.
Signed-off-by: Mike Leach <redacted>
---
drivers/hwtracing/coresight/Makefile | 3 +-
.../hwtracing/coresight/coresight-cfg-afdo.c | 154 ++++++++++++++++++
.../coresight/coresight-cfg-preload.c | 25 +++
.../coresight/coresight-cfg-preload.h | 11 ++
drivers/hwtracing/coresight/coresight-core.c | 6 +
.../hwtracing/coresight/coresight-syscfg.h | 1 +
6 files changed, 199 insertions(+), 1 deletion(-)
create mode 100644 drivers/hwtracing/coresight/coresight-cfg-afdo.c
create mode 100644 drivers/hwtracing/coresight/coresight-cfg-preload.c
create mode 100644 drivers/hwtracing/coresight/coresight-cfg-preload.h
@@ -0,0 +1,154 @@+// SPDX-License-Identifier: GPL-2.0+/*+*Copyright(C)2020LinaroLimited.Allrightsreserved.+*Author:MikeLeach<mike.leach@linaro.org>+*/++#include"coresight-config.h"+#include"coresight-etm4x-cfg.h"++/* preload configurations and features */++/* preload in features for ETMv4 */++/* strobe feature */+staticstructcscfg_parameter_descstrobe_params[]={+{+.name="window",+.value=5000,+},+{+.name="period",+.value=10000,+},+};++staticstructcscfg_regval_descstrobe_regs[]={+/* resource selectors */+{+.type=CS_CFG_REG_TYPE_RESOURCE,+.offset=TRCRSCTLRn(2),+.hw_info=ETM4_CFG_RES_SEL,+.val32=0x20001,+},+{+.type=CS_CFG_REG_TYPE_RESOURCE,+.offset=TRCRSCTLRn(3),+.hw_info=ETM4_CFG_RES_SEQ,+.val32=0x20002,+},+/* strobe window counter 0 - reload from param 0 */+{+.type=CS_CFG_REG_TYPE_RESOURCE|CS_CFG_REG_TYPE_VAL_SAVE,+.offset=TRCCNTVRn(0),+.hw_info=ETM4_CFG_RES_CTR,+},+{+.type=CS_CFG_REG_TYPE_RESOURCE|CS_CFG_REG_TYPE_VAL_PARAM,+.offset=TRCCNTRLDVRn(0),+.hw_info=ETM4_CFG_RES_CTR,+.val32=0,+},+{+.type=CS_CFG_REG_TYPE_RESOURCE,+.offset=TRCCNTCTLRn(0),+.hw_info=ETM4_CFG_RES_CTR,+.val32=0x10001,+},+/* strobe period counter 1 - reload from param 1 */+{+.type=CS_CFG_REG_TYPE_RESOURCE|CS_CFG_REG_TYPE_VAL_SAVE,+.offset=TRCCNTVRn(1),+.hw_info=ETM4_CFG_RES_CTR,+},+{+.type=CS_CFG_REG_TYPE_RESOURCE|CS_CFG_REG_TYPE_VAL_PARAM,+.offset=TRCCNTRLDVRn(1),+.hw_info=ETM4_CFG_RES_CTR,+.val32=1,+},+{+.type=CS_CFG_REG_TYPE_RESOURCE,+.offset=TRCCNTCTLRn(1),+.hw_info=ETM4_CFG_RES_CTR,+.val32=0x8102,+},+/* sequencer */+{+.type=CS_CFG_REG_TYPE_RESOURCE,+.offset=TRCSEQEVRn(0),+.hw_info=ETM4_CFG_RES_SEQ,+.val32=0x0081,+},+{+.type=CS_CFG_REG_TYPE_RESOURCE,+.offset=TRCSEQEVRn(1),+.hw_info=ETM4_CFG_RES_SEQ,+.val32=0x0000,+},+/* view-inst */+{+.type=CS_CFG_REG_TYPE_STD|CS_CFG_REG_TYPE_VAL_MASK,+.offset=TRCVICTLR,+.val32=0x0003,+.mask32=0x0003,+},+/* end of regs */+};++structcscfg_feature_descstrobe={+.name="strobing",+.brief="Generate periodic trace capture windows.\n"+"parameter \'window\': a number of CPU cycles (W)\n"+"parameter \'period\': trace enabled for W cycles every period x W cycles\n",+.match_flags=CS_CFG_MATCH_CLASS_SRC_ETM4,+.nr_params=ARRAY_SIZE(strobe_params),+.params=strobe_params,+.nr_regs=ARRAY_SIZE(strobe_regs),+.regs=strobe_regs,+};++/* create an autofdo configuration */++/* we will provide 9 sets of preset parameter values */+#define AFDO_NR_PRESETS 9+/* the total number of parameters in used features */+#define AFDO_NR_PARAM_SUM ARRAY_SIZE(strobe_params)++#define AFDO_MATCH_STROBING (CS_CFG_MATCH_INST_ANY | CS_CFG_MATCH_CLASS_SRC_ETM4)++staticstructcscfg_config_feat_refafdo_refs[]={+{+.name="strobing",+.match={+.match_flags=AFDO_MATCH_STROBING,+},+},+};++/*+*setofpresetsleavesstrobingwindowconstantwhilevaryingperiodtoallow+*experimentationwithmark/spaceratiosforvariousworkloads+*/+staticu64afdo_presets[AFDO_NR_PRESETS][AFDO_NR_PARAM_SUM]={+{5000,2},+{5000,4},+{5000,8},+{5000,16},+{5000,64},+{5000,128},+{5000,512},+{5000,1024},+{5000,4096},+};++structcscfg_config_descafdo={+.name="autofdo",+.brief="Setup ETMs with strobing for autofdo\n"+"Supplied presets allow experimentation with mark-space ratio for various loads\n",+.nr_refs=ARRAY_SIZE(afdo_refs),+.refs=afdo_refs,+.nr_presets=AFDO_NR_PRESETS,+.nr_total_params=AFDO_NR_PARAM_SUM,+.presets=&afdo_presets[0][0],+};
On Thu, Jan 28, 2021 at 05:09:34PM +0000, Mike Leach wrote:
quoted hunk
Preload set of configurations.
This patch creates a small set of preloaded configurations and features
that are available immediately after coresight has been initialised.
The current set provides a strobing feature for ETMv4, that creates a
periodic sampling of trace by switching trace generation on and off
using counters in the ETM.
A configuration called "autofdo" is also provided that uses the 'strobing'
feature and provides a couple of preset values, selectable on the perf
command line.
Signed-off-by: Mike Leach <redacted>
---
drivers/hwtracing/coresight/Makefile | 3 +-
.../hwtracing/coresight/coresight-cfg-afdo.c | 154 ++++++++++++++++++
.../coresight/coresight-cfg-preload.c | 25 +++
.../coresight/coresight-cfg-preload.h | 11 ++
drivers/hwtracing/coresight/coresight-core.c | 6 +
.../hwtracing/coresight/coresight-syscfg.h | 1 +
6 files changed, 199 insertions(+), 1 deletion(-)
create mode 100644 drivers/hwtracing/coresight/coresight-cfg-afdo.c
create mode 100644 drivers/hwtracing/coresight/coresight-cfg-preload.c
create mode 100644 drivers/hwtracing/coresight/coresight-cfg-preload.h
@@ -0,0 +1,154 @@+// SPDX-License-Identifier: GPL-2.0+/*+*Copyright(C)2020LinaroLimited.Allrightsreserved.+*Author:MikeLeach<mike.leach@linaro.org>+*/++#include"coresight-config.h"+#include"coresight-etm4x-cfg.h"++/* preload configurations and features */++/* preload in features for ETMv4 */++/* strobe feature */+staticstructcscfg_parameter_descstrobe_params[]={+{+.name="window",+.value=5000,+},+{+.name="period",+.value=10000,+},+};++staticstructcscfg_regval_descstrobe_regs[]={+/* resource selectors */+{+.type=CS_CFG_REG_TYPE_RESOURCE,+.offset=TRCRSCTLRn(2),+.hw_info=ETM4_CFG_RES_SEL,+.val32=0x20001,+},+{+.type=CS_CFG_REG_TYPE_RESOURCE,+.offset=TRCRSCTLRn(3),+.hw_info=ETM4_CFG_RES_SEQ,+.val32=0x20002,+},+/* strobe window counter 0 - reload from param 0 */+{+.type=CS_CFG_REG_TYPE_RESOURCE|CS_CFG_REG_TYPE_VAL_SAVE,+.offset=TRCCNTVRn(0),+.hw_info=ETM4_CFG_RES_CTR,+},+{+.type=CS_CFG_REG_TYPE_RESOURCE|CS_CFG_REG_TYPE_VAL_PARAM,+.offset=TRCCNTRLDVRn(0),+.hw_info=ETM4_CFG_RES_CTR,+.val32=0,+},+{+.type=CS_CFG_REG_TYPE_RESOURCE,+.offset=TRCCNTCTLRn(0),+.hw_info=ETM4_CFG_RES_CTR,+.val32=0x10001,+},+/* strobe period counter 1 - reload from param 1 */+{+.type=CS_CFG_REG_TYPE_RESOURCE|CS_CFG_REG_TYPE_VAL_SAVE,+.offset=TRCCNTVRn(1),+.hw_info=ETM4_CFG_RES_CTR,+},+{+.type=CS_CFG_REG_TYPE_RESOURCE|CS_CFG_REG_TYPE_VAL_PARAM,+.offset=TRCCNTRLDVRn(1),+.hw_info=ETM4_CFG_RES_CTR,+.val32=1,+},+{+.type=CS_CFG_REG_TYPE_RESOURCE,+.offset=TRCCNTCTLRn(1),+.hw_info=ETM4_CFG_RES_CTR,+.val32=0x8102,+},+/* sequencer */+{+.type=CS_CFG_REG_TYPE_RESOURCE,+.offset=TRCSEQEVRn(0),+.hw_info=ETM4_CFG_RES_SEQ,+.val32=0x0081,+},+{+.type=CS_CFG_REG_TYPE_RESOURCE,+.offset=TRCSEQEVRn(1),+.hw_info=ETM4_CFG_RES_SEQ,+.val32=0x0000,+},+/* view-inst */+{+.type=CS_CFG_REG_TYPE_STD|CS_CFG_REG_TYPE_VAL_MASK,+.offset=TRCVICTLR,+.val32=0x0003,+.mask32=0x0003,+},+/* end of regs */+};++structcscfg_feature_descstrobe={+.name="strobing",+.brief="Generate periodic trace capture windows.\n"+"parameter \'window\': a number of CPU cycles (W)\n"+"parameter \'period\': trace enabled for W cycles every period x W cycles\n",+.match_flags=CS_CFG_MATCH_CLASS_SRC_ETM4,+.nr_params=ARRAY_SIZE(strobe_params),+.params=strobe_params,+.nr_regs=ARRAY_SIZE(strobe_regs),+.regs=strobe_regs,+};++/* create an autofdo configuration */++/* we will provide 9 sets of preset parameter values */+#define AFDO_NR_PRESETS 9+/* the total number of parameters in used features */+#define AFDO_NR_PARAM_SUM ARRAY_SIZE(strobe_params)++#define AFDO_MATCH_STROBING (CS_CFG_MATCH_INST_ANY | CS_CFG_MATCH_CLASS_SRC_ETM4)++staticstructcscfg_config_feat_refafdo_refs[]={+{+.name="strobing",+.match={+.match_flags=AFDO_MATCH_STROBING,+},+},+};++/*+*setofpresetsleavesstrobingwindowconstantwhilevaryingperiodtoallow+*experimentationwithmark/spaceratiosforvariousworkloads+*/+staticu64afdo_presets[AFDO_NR_PRESETS][AFDO_NR_PARAM_SUM]={+{5000,2},+{5000,4},+{5000,8},+{5000,16},+{5000,64},+{5000,128},+{5000,512},+{5000,1024},+{5000,4096},+};++structcscfg_config_descafdo={+.name="autofdo",+.brief="Setup ETMs with strobing for autofdo\n"+"Supplied presets allow experimentation with mark-space ratio for various loads\n",+.nr_refs=ARRAY_SIZE(afdo_refs),+.refs=afdo_refs,+.nr_presets=AFDO_NR_PRESETS,+.nr_total_params=AFDO_NR_PARAM_SUM,+.presets=&afdo_presets[0][0],+};
From: Suzuki K Poulose <suzuki.poulose@arm.com> Date: 2021-03-05 13:40:00
On 1/28/21 5:09 PM, Mike Leach wrote:
quoted hunk
Preload set of configurations.
This patch creates a small set of preloaded configurations and features
that are available immediately after coresight has been initialised.
The current set provides a strobing feature for ETMv4, that creates a
periodic sampling of trace by switching trace generation on and off
using counters in the ETM.
A configuration called "autofdo" is also provided that uses the 'strobing'
feature and provides a couple of preset values, selectable on the perf
command line.
Signed-off-by: Mike Leach <redacted>
---
drivers/hwtracing/coresight/Makefile | 3 +-
.../hwtracing/coresight/coresight-cfg-afdo.c | 154 ++++++++++++++++++
.../coresight/coresight-cfg-preload.c | 25 +++
.../coresight/coresight-cfg-preload.h | 11 ++
drivers/hwtracing/coresight/coresight-core.c | 6 +
.../hwtracing/coresight/coresight-syscfg.h | 1 +
6 files changed, 199 insertions(+), 1 deletion(-)
create mode 100644 drivers/hwtracing/coresight/coresight-cfg-afdo.c
create mode 100644 drivers/hwtracing/coresight/coresight-cfg-preload.c
create mode 100644 drivers/hwtracing/coresight/coresight-cfg-preload.h
@@ -0,0 +1,154 @@+// SPDX-License-Identifier: GPL-2.0+/*+*Copyright(C)2020LinaroLimited.Allrightsreserved.+*Author:MikeLeach<mike.leach@linaro.org>+*/++#include"coresight-config.h"+#include"coresight-etm4x-cfg.h"++/* preload configurations and features */++/* preload in features for ETMv4 */++/* strobe feature */+staticstructcscfg_parameter_descstrobe_params[]={+{+.name="window",+.value=5000,+},+{+.name="period",+.value=10000,+},+};++staticstructcscfg_regval_descstrobe_regs[]={+/* resource selectors */+{+.type=CS_CFG_REG_TYPE_RESOURCE,+.offset=TRCRSCTLRn(2),+.hw_info=ETM4_CFG_RES_SEL,+.val32=0x20001,+},+{+.type=CS_CFG_REG_TYPE_RESOURCE,+.offset=TRCRSCTLRn(3),+.hw_info=ETM4_CFG_RES_SEQ,+.val32=0x20002,+},+/* strobe window counter 0 - reload from param 0 */+{+.type=CS_CFG_REG_TYPE_RESOURCE|CS_CFG_REG_TYPE_VAL_SAVE,+.offset=TRCCNTVRn(0),+.hw_info=ETM4_CFG_RES_CTR,+},+{+.type=CS_CFG_REG_TYPE_RESOURCE|CS_CFG_REG_TYPE_VAL_PARAM,+.offset=TRCCNTRLDVRn(0),+.hw_info=ETM4_CFG_RES_CTR,+.val32=0,+},+{+.type=CS_CFG_REG_TYPE_RESOURCE,+.offset=TRCCNTCTLRn(0),+.hw_info=ETM4_CFG_RES_CTR,+.val32=0x10001,+},+/* strobe period counter 1 - reload from param 1 */+{+.type=CS_CFG_REG_TYPE_RESOURCE|CS_CFG_REG_TYPE_VAL_SAVE,+.offset=TRCCNTVRn(1),+.hw_info=ETM4_CFG_RES_CTR,+},+{+.type=CS_CFG_REG_TYPE_RESOURCE|CS_CFG_REG_TYPE_VAL_PARAM,+.offset=TRCCNTRLDVRn(1),+.hw_info=ETM4_CFG_RES_CTR,+.val32=1,+},+{+.type=CS_CFG_REG_TYPE_RESOURCE,+.offset=TRCCNTCTLRn(1),+.hw_info=ETM4_CFG_RES_CTR,+.val32=0x8102,+},+/* sequencer */+{+.type=CS_CFG_REG_TYPE_RESOURCE,+.offset=TRCSEQEVRn(0),+.hw_info=ETM4_CFG_RES_SEQ,+.val32=0x0081,+},+{+.type=CS_CFG_REG_TYPE_RESOURCE,+.offset=TRCSEQEVRn(1),+.hw_info=ETM4_CFG_RES_SEQ,+.val32=0x0000,+},+/* view-inst */+{+.type=CS_CFG_REG_TYPE_STD|CS_CFG_REG_TYPE_VAL_MASK,+.offset=TRCVICTLR,+.val32=0x0003,+.mask32=0x0003,+},+/* end of regs */+};++structcscfg_feature_descstrobe={+.name="strobing",+.brief="Generate periodic trace capture windows.\n"+"parameter \'window\': a number of CPU cycles (W)\n"+"parameter \'period\': trace enabled for W cycles every period x W cycles\n",
nit: Could we align the string as below:
.brief = "Generate periodic trace capture windows.\n"
"parameter \'window\': a number of CPU cycles (W)\n"
"parameter \'period\': trace enabled for W cycles every period x W cycles\n",
+ .match_flags = CS_CFG_MATCH_CLASS_SRC_ETM4,
+ .nr_params = ARRAY_SIZE(strobe_params),
+ .params = strobe_params,
+ .nr_regs = ARRAY_SIZE(strobe_regs),
+ .regs = strobe_regs,
+};
+
+/* create an autofdo configuration */
+
+/* we will provide 9 sets of preset parameter values */
+#define AFDO_NR_PRESETS 9
+/* the total number of parameters in used features */
+#define AFDO_NR_PARAM_SUM ARRAY_SIZE(strobe_params)
nit: alignment consistency. i.e 1 TAB vs 2 TABs (with AFDO_NR_PRESETS)
minor nit : s/AFDO_NR_PARAM_SUM/AFDO_NR_TOTAL_PARAMS ? or even AFDO_NR_PARAMS
+
+#define AFDO_MATCH_STROBING (CS_CFG_MATCH_INST_ANY | CS_CFG_MATCH_CLASS_SRC_ETM4)
+
+static struct cscfg_config_feat_ref afdo_refs[] = {
+ {
+ .name = "strobing",
+ .match = {
+ .match_flags = AFDO_MATCH_STROBING,
+ },
+ },
+};
+
+/*
+ * set of presets leaves strobing window constant while varying period to allow
+ * experimentation with mark / space ratios for various workloads
+ */
+static u64 afdo_presets[AFDO_NR_PRESETS][AFDO_NR_PARAM_SUM] = {
+ { 5000, 2 },
+ { 5000, 4 },
+ { 5000, 8 },
+ { 5000, 16 },
+ { 5000, 64 },
+ { 5000, 128 },
+ { 5000, 512 },
+ { 5000, 1024 },
+ { 5000, 4096 },
+};
+
+struct cscfg_config_desc afdo = {
+ .name = "autofdo",
+ .brief = "Setup ETMs with strobing for autofdo\n"
+ "Supplied presets allow experimentation with mark-space ratio for various loads\n",
@@ -1744,9 +1744,15 @@ static int __init coresight_init(void)/* initialise the coresight syscfg API */ret=cscfg_init();+if(ret)+gotoexit_perf_close;++/* preload builtin configurations */+ret=cscfg_preload();if(!ret)return0;
Could this be folded into cscfg_init() ?
Otherwise looks fine to me
Suzuki
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
From: Mike Leach <hidden> Date: 2021-01-28 17:48:27
Configurations are first activated, then when any coresight device is
enabled, the active configurations are checked and any matching
one is enabled.
This patch provides the activation / enable API.
Signed-off-by: Mike Leach <redacted>
---
.../hwtracing/coresight/coresight-config.h | 2 +
.../hwtracing/coresight/coresight-syscfg.c | 127 ++++++++++++++++++
.../hwtracing/coresight/coresight-syscfg.h | 10 +-
include/linux/coresight.h | 2 +
4 files changed, 140 insertions(+), 1 deletion(-)
@@ -298,6 +298,7 @@ static int cscfg_load_config(struct cscfg_config_desc *cfg_desc)returnerr;list_add(&cfg_desc->item,&cscfg_mgr->data.config_desc_list);+atomic_set(&cfg_desc->active_cnt,0);return0;}
@@ -477,6 +478,131 @@ void cscfg_unregister_csdev(struct coresight_device *csdev)}EXPORT_SYMBOL_GPL(cscfg_unregister_csdev);+voidcscfg_csdev_reset_feats(structcoresight_device*csdev)+{+structcscfg_feature_csdev*feat;++mutex_lock(&cscfg_csdev_mutex);+if(list_empty(&csdev->feature_csdev_list))+gotounlock_exit;++list_for_each_entry(feat,&csdev->feature_csdev_list,node)+cscfg_reset_feat(feat);++unlock_exit:+mutex_unlock(&cscfg_csdev_mutex);+}+EXPORT_SYMBOL_GPL(cscfg_csdev_reset_feats);++/**+*Markaconfigdescriptorasactive.+*Thiswillbeseenwhencsdevdevicesareactivatedinthesystem.+*+*Selectionbyhashvalue-generatedfromtheconfigurationnamewhenit+*wasloadedandaddedtothecs_etm/configurationsfilesystemforselection+*byperf.+*+*@cfg_hash:Hashvalueoftheselectedconfigurationname.+*/+intcscfg_activate_config(unsignedlongcfg_hash)+{+structcscfg_config_desc*curr_item,*match_item=0;++mutex_lock(&cscfg_mutex);++list_for_each_entry(curr_item,&cscfg_mgr->data.config_desc_list,item){+if((unsignedlong)curr_item->id_ea->var==cfg_hash){+match_item=curr_item;+atomic_inc(&cscfg_mgr->data.sys_active_cnt);+break;+}+}+mutex_unlock(&cscfg_mutex);++if(!match_item)+return-EINVAL;++dev_dbg(to_device_cscfg(),"Activate config %s.\n",match_item->name);++/* mark the descriptors as active so enable config will use them */+mutex_lock(&cscfg_csdev_mutex);+atomic_inc(&match_item->active_cnt);+mutex_unlock(&cscfg_csdev_mutex);++return0;+}+EXPORT_SYMBOL_GPL(cscfg_activate_config);++voidcscfg_deactivate_config(unsignedlongcfg_hash)+{+structcscfg_config_desc*curr_item,*match_item=0;++mutex_lock(&cscfg_mutex);++list_for_each_entry(curr_item,&cscfg_mgr->data.config_desc_list,item){+if((unsignedlong)curr_item->id_ea->var==cfg_hash){+match_item=curr_item;+break;+}+}+mutex_unlock(&cscfg_mutex);+if(!match_item)+return;++dev_dbg(to_device_cscfg(),"Deactivate config %s.\n",match_item->name);++mutex_lock(&cscfg_csdev_mutex);+atomic_dec(&match_item->active_cnt);+mutex_unlock(&cscfg_csdev_mutex);++atomic_dec(&cscfg_mgr->data.sys_active_cnt);+}+EXPORT_SYMBOL_GPL(cscfg_deactivate_config);++/* Find and program any active config for the supplied device.*/+intcscfg_csdev_enable_active_config(structcoresight_device*csdev,+unsignedlongid_hash,intpreset)+{+structcscfg_config_csdev*cfg=NULL,*item;+conststructcscfg_config_desc*desc;+interr=0;++/* quickly check global count */+if(!atomic_read(&cscfg_mgr->data.sys_active_cnt))+return0;++mutex_lock(&cscfg_csdev_mutex);+list_for_each_entry(item,&csdev->config_csdev_list,node){+desc=item->desc;+if((atomic_read(&desc->active_cnt))&&+((unsignedlong)desc->id_ea->var==id_hash)){+cfg=item;+break;+}+}+if(cfg){+err=cscfg_csdev_enable_config(cfg,preset);+if(!err)+csdev->active_cfg_ctxt=(void*)cfg;+}+mutex_unlock(&cscfg_csdev_mutex);+returnerr;+}+EXPORT_SYMBOL_GPL(cscfg_csdev_enable_active_config);++/* save and disable the active config for the device */+voidcscfg_csdev_disable_active_config(structcoresight_device*csdev)+{+structcscfg_config_csdev*cfg;++mutex_lock(&cscfg_csdev_mutex);+cfg=(structcscfg_config_csdev*)csdev->active_cfg_ctxt;+if(cfg)+cscfg_csdev_disable_config(cfg);+mutex_unlock(&cscfg_csdev_mutex);+}+EXPORT_SYMBOL_GPL(cscfg_csdev_disable_active_config);+/* Initialise system configuration management device. */structdevice*to_device_cscfg(void)
@@ -546,6 +672,7 @@ int __init cscfg_init(void)INIT_LIST_HEAD(&cscfg_mgr->data.feat_desc_list);INIT_LIST_HEAD(&cscfg_mgr->data.config_desc_list);cscfg_mgr->data.nr_csdev=0;+atomic_set(&cscfg_mgr->data.sys_active_cnt,0);dev_info(to_device_cscfg(),"CoreSight Configuration manager initialised");return0;
On Thu, Jan 28, 2021 at 05:09:31PM +0000, Mike Leach wrote:
quoted hunk
Configurations are first activated, then when any coresight device is
enabled, the active configurations are checked and any matching
one is enabled.
This patch provides the activation / enable API.
Signed-off-by: Mike Leach <redacted>
---
.../hwtracing/coresight/coresight-config.h | 2 +
.../hwtracing/coresight/coresight-syscfg.c | 127 ++++++++++++++++++
.../hwtracing/coresight/coresight-syscfg.h | 10 +-
include/linux/coresight.h | 2 +
4 files changed, 140 insertions(+), 1 deletion(-)
It would be nice to have a comment that mentions why this is needed. I had to
go look in patch 09 to see that it prevents a feature from being changed when
any configuration is active. And since patch 09 is the only place where
@sys_active_cnt is used, please move the declaration and handling of the
variable there.
+ break;
+ }
+ }
+ mutex_unlock(&cscfg_mutex);
+
+ if (!match_item)
+ return -EINVAL;
+
+ dev_dbg(to_device_cscfg(), "Activate config %s.\n", match_item->name);
+
+ /* mark the descriptors as active so enable config will use them */
+ mutex_lock(&cscfg_csdev_mutex);
+ atomic_inc(&match_item->active_cnt);
What is ->active_cnt used for? I see it referenced in
cscfg_csdev_enable_active_config() but it doesn't do much other than to confirm
the configuration has been activated by someone.
There is also a chance that a caller would call cscfg_activate_config() once and
call cscfg_csdev_enable_active_config() multiple time, which would really create
problems. I would move the incrementation of sys_active_cnt within the mutex
hold in cscfg_csdev_enable_active_config() and get rid of ->active_cnt. If I am
correct we wouldn't need cscfg_activate_config() after that.
+
+/**
+ * Mark a config descriptor as active.
+ * This will be seen when csdev devices are activated in the system.
+ *
+ * Selection by hash value - generated from the configuration name when it
+ * was loaded and added to the cs_etm/configurations file system for selection
+ * by perf.
+ *
+ * @cfg_hash: Hash value of the selected configuration name.
+ */
+int cscfg_activate_config(unsigned long cfg_hash)
+{
+ struct cscfg_config_desc *curr_item, *match_item = 0;
+
+ mutex_lock(&cscfg_mutex);
+
+ list_for_each_entry(curr_item, &cscfg_mgr->data.config_desc_list, item) {
+ if ((unsigned long)curr_item->id_ea->var == cfg_hash) {
+ match_item = curr_item;
+ atomic_inc(&cscfg_mgr->data.sys_active_cnt);
It would be nice to have a comment that mentions why this is needed. I had to
go look in patch 09 to see that it prevents a feature from being changed when
any configuration is active. And since patch 09 is the only place where
@sys_active_cnt is used, please move the declaration and handling of the
variable there.
quoted
+ break;
+ }
+ }
+ mutex_unlock(&cscfg_mutex);
+
+ if (!match_item)
+ return -EINVAL;
+
+ dev_dbg(to_device_cscfg(), "Activate config %s.\n", match_item->name);
+
+ /* mark the descriptors as active so enable config will use them */
+ mutex_lock(&cscfg_csdev_mutex);
+ atomic_inc(&match_item->active_cnt);
What is ->active_cnt used for? I see it referenced in
cscfg_csdev_enable_active_config() but it doesn't do much other than to confirm
the configuration has been activated by someone.
There is also a chance that a caller would call cscfg_activate_config() once and
call cscfg_csdev_enable_active_config() multiple time, which would really create
problems. I would move the incrementation of sys_active_cnt within the mutex
hold in cscfg_csdev_enable_active_config() and get rid of ->active_cnt. If I am
correct we wouldn't need cscfg_activate_config() after that.
I looked at patch 06 and I understand why incrementing sys_active_cnt has to be
done before enabling it. If it wasn't so someone could update the feature
between the time setup_aux() is called and the event is installed on a CPU. As
such cscfg_activate_config() should stay but I still think ->active_cnt should
go.
From: Mike Leach <hidden> Date: 2021-02-26 20:18:26
HI Mathieu,
On Thu, 25 Feb 2021 at 21:20, Mathieu Poirier
[off-list ref] wrote:
On Thu, Jan 28, 2021 at 05:09:31PM +0000, Mike Leach wrote:
quoted
Configurations are first activated, then when any coresight device is
enabled, the active configurations are checked and any matching
one is enabled.
This patch provides the activation / enable API.
Signed-off-by: Mike Leach <redacted>
---
.../hwtracing/coresight/coresight-config.h | 2 +
.../hwtracing/coresight/coresight-syscfg.c | 127 ++++++++++++++++++
.../hwtracing/coresight/coresight-syscfg.h | 10 +-
include/linux/coresight.h | 2 +
4 files changed, 140 insertions(+), 1 deletion(-)
It would be nice to have a comment that mentions why this is needed. I had to
go look in patch 09 to see that it prevents a feature from being changed when
any configuration is active. And since patch 09 is the only place where
@sys_active_cnt is used, please move the declaration and handling of the
variable there.
sys_active_cnt is used later in this patch in
cscfg_csdev_enable_active_config().
In that case it is to give a fast exit to the enable function if
nothing is actually active. The set is written so that the process of
enabling or disabling the config onto an actual device is effiecient
as possible - as this can happen frequently and across many devices.
quoted
+ break;
+ }
+ }
+ mutex_unlock(&cscfg_mutex);
+
+ if (!match_item)
+ return -EINVAL;
+
+ dev_dbg(to_device_cscfg(), "Activate config %s.\n", match_item->name);
+
+ /* mark the descriptors as active so enable config will use them */
+ mutex_lock(&cscfg_csdev_mutex);
+ atomic_inc(&match_item->active_cnt);
What is ->active_cnt used for? I see it referenced in
cscfg_csdev_enable_active_config() but it doesn't do much other than to confirm
the configuration has been activated by someone.
There is also a chance that a caller would call cscfg_activate_config() once and
call cscfg_csdev_enable_active_config() multiple time, which would really create
problems. I would move the incrementation of sys_active_cnt within the mutex
hold in cscfg_csdev_enable_active_config() and get rid of ->active_cnt. If I am
correct we wouldn't need cscfg_activate_config() after that.
The activate / enable paradigm was developed when I was working on the
dynamic feature load / unload in the follow up sets.
A little of this has been pulled in here - just enough of the
framework to get the built-in config going.
The idea is that activate is called first - in this set perf calls it
as it sets up / tears down and auxtrace session. In a later patchset,
configfs will call it to activate a configuration to allow it for be
active for sysfs controlled coresight.
This also ensures that the configuration cannot be removed while it is
needed, as you have observed in you next e-mail.
Then as any (etm) device has the perf event on it and enabled, the
cscfg_enable_active_config for the specific instance is then called.
This is deliberately independent of the activate process - activate is
system global, enable is per device. Therefore as an event moves
across ETMs, the relevent ETM will have the configuration activated.
The cscfg_enable_active_config() call matches the incoming config_hash
with an active config ( ->active_cnt) and if it finds this then a call
is made to do the actual activation on csdev. This it does more than
just check for the active configuration.
This arrangement allows for different sessions of perf to have
different active configurations (looking to the near future when it
will be possible to support multiple perf sessions on 1:1 topologies).
It also validates that the requested configuration for enable, has
actually been activated.
That said - active_cnt could be dropped if we don't want the
additiional validation. (in the original dynamic load set I was
considering allowing unload of inactive configs even if others were
active - but that was too complicated and unnecessary).
Thanks
Mike
@@ -245,6 +246,7 @@ struct coresight_device {/* system configuration and feature lists */structlist_headfeature_csdev_list;structlist_headconfig_csdev_list;+void*active_cfg_ctxt;};/*--
2.17.1
--
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
From: Suzuki K Poulose <suzuki.poulose@arm.com> Date: 2021-03-04 16:51:16
On 1/28/21 5:09 PM, Mike Leach wrote:
quoted hunk
Configurations are first activated, then when any coresight device is
enabled, the active configurations are checked and any matching
one is enabled.
This patch provides the activation / enable API.
Signed-off-by: Mike Leach <redacted>
---
.../hwtracing/coresight/coresight-config.h | 2 +
.../hwtracing/coresight/coresight-syscfg.c | 127 ++++++++++++++++++
.../hwtracing/coresight/coresight-syscfg.h | 10 +-
include/linux/coresight.h | 2 +
4 files changed, 140 insertions(+), 1 deletion(-)
+
+ mutex_lock(&cscfg_mutex);
+
+ list_for_each_entry(curr_item, &cscfg_mgr->data.config_desc_list, item) {
+ if ((unsigned long)curr_item->id_ea->var == cfg_hash) {
+ match_item = curr_item;
+ atomic_inc(&cscfg_mgr->data.sys_active_cnt);
+ break;
+ }
+ }
+ mutex_unlock(&cscfg_mutex);
+
+ if (!match_item)
+ return -EINVAL;
+
+ dev_dbg(to_device_cscfg(), "Activate config %s.\n", match_item->name);
+
+ /* mark the descriptors as active so enable config will use them */
+ mutex_lock(&cscfg_csdev_mutex);
+ atomic_inc(&match_item->active_cnt);
+ mutex_unlock(&cscfg_csdev_mutex);
Is there a guarantee that this item is active and present in the list after
we dropped the mutex above ? We could certainly nest the mutex as long as
we follow the order everywhere to prevent such a race.
quoted hunk
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cscfg_activate_config);
+
+void cscfg_deactivate_config(unsigned long cfg_hash)
+{
+ struct cscfg_config_desc *curr_item, *match_item = 0;
+
+ mutex_lock(&cscfg_mutex);
+
+ list_for_each_entry(curr_item, &cscfg_mgr->data.config_desc_list, item) {
+ if ((unsigned long)curr_item->id_ea->var == cfg_hash) {
+ match_item = curr_item;
+ break;
+ }
+ }
+ mutex_unlock(&cscfg_mutex);
+ if (!match_item)
+ return;
+
+ dev_dbg(to_device_cscfg(), "Deactivate config %s.\n", match_item->name);
+
+ mutex_lock(&cscfg_csdev_mutex);
+ atomic_dec(&match_item->active_cnt);
+ mutex_unlock(&cscfg_csdev_mutex);
+
+ atomic_dec(&cscfg_mgr->data.sys_active_cnt);
+}
+EXPORT_SYMBOL_GPL(cscfg_deactivate_config);
+
+/* Find and program any active config for the supplied device.*/
+int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
+ unsigned long id_hash, int preset)
+{
+ struct cscfg_config_csdev *cfg = NULL, *item;
+ const struct cscfg_config_desc *desc;
+ int err = 0;
+
+ /* quickly check global count */
+ if (!atomic_read(&cscfg_mgr->data.sys_active_cnt))
+ return 0;
+
+ mutex_lock(&cscfg_csdev_mutex);
+ list_for_each_entry(item, &csdev->config_csdev_list, node) {
+ desc = item->desc;
+ if ((atomic_read(&desc->active_cnt)) &&
+ ((unsigned long)desc->id_ea->var == id_hash)) {
+ cfg = item;
+ break;
+ }
+ }
+ if (cfg) {
+ err = cscfg_csdev_enable_config(cfg, preset);
+ if (!err)
+ csdev->active_cfg_ctxt = (void *)cfg;
+ }
+ mutex_unlock(&cscfg_csdev_mutex);
+ return err;
+}
+EXPORT_SYMBOL_GPL(cscfg_csdev_enable_active_config);
+
+/* save and disable the active config for the device */
+void cscfg_csdev_disable_active_config(struct coresight_device *csdev)
+{
+ struct cscfg_config_csdev *cfg;
+
+ mutex_lock(&cscfg_csdev_mutex);
+ cfg = (struct cscfg_config_csdev *)csdev->active_cfg_ctxt;
+ if (cfg)
+ cscfg_csdev_disable_config(cfg);
+ mutex_unlock(&cscfg_csdev_mutex);
+}
+EXPORT_SYMBOL_GPL(cscfg_csdev_disable_active_config);
+
/* Initialise system configuration management device. */
struct device *to_device_cscfg(void)
nit: Is this aligned ? (It is from Patch 1, though).
* @config_desc_list: List of system configuration descriptors to load into registered devices.
- * @nr_csdev: Number of registered devices with the cscfg system
+ * @nr_csdev: Number of registered devices with the cscfg system
Spurious change ?
quoted hunk
+ * @sys_active_cnt: Total number of active config descriptor references.
*/
struct cscfg_api_data {
struct list_head csdev_desc_list;
struct list_head feat_desc_list;
struct list_head config_desc_list;
int nr_csdev;
+ atomic_t sys_active_cnt;
};
/**
@@ -53,6 +55,12 @@ int cscfg_register_csdev(struct coresight_device *csdev, struct cscfg_match_desc *info, struct cscfg_csdev_feat_ops *ops); void cscfg_unregister_csdev(struct coresight_device *csdev);+int cscfg_activate_config(unsigned long cfg_hash);+void cscfg_deactivate_config(unsigned long cfg_hash);+void cscfg_csdev_reset_feats(struct coresight_device *csdev);+int cscfg_csdev_enable_active_config(struct coresight_device *csdev,+ unsigned long id_hash, int preset);+void cscfg_csdev_disable_active_config(struct coresight_device *csdev); /** * System configuration manager device.
From: Mike Leach <hidden> Date: 2021-03-04 18:16:59
Hi Suzuki,
On Thu, 4 Mar 2021 at 16:49, Suzuki K Poulose [off-list ref] wrote:
On 1/28/21 5:09 PM, Mike Leach wrote:
quoted
Configurations are first activated, then when any coresight device is
enabled, the active configurations are checked and any matching
one is enabled.
This patch provides the activation / enable API.
Signed-off-by: Mike Leach <redacted>
---
.../hwtracing/coresight/coresight-config.h | 2 +
.../hwtracing/coresight/coresight-syscfg.c | 127 ++++++++++++++++++
.../hwtracing/coresight/coresight-syscfg.h | 10 +-
include/linux/coresight.h | 2 +
4 files changed, 140 insertions(+), 1 deletion(-)
+
+ mutex_lock(&cscfg_mutex);
+
+ list_for_each_entry(curr_item, &cscfg_mgr->data.config_desc_list, item) {
+ if ((unsigned long)curr_item->id_ea->var == cfg_hash) {
+ match_item = curr_item;
+ atomic_inc(&cscfg_mgr->data.sys_active_cnt);
+ break;
+ }
+ }
+ mutex_unlock(&cscfg_mutex);
+
+ if (!match_item)
+ return -EINVAL;
+
+ dev_dbg(to_device_cscfg(), "Activate config %s.\n", match_item->name);
+
+ /* mark the descriptors as active so enable config will use them */
+ mutex_lock(&cscfg_csdev_mutex);
+ atomic_inc(&match_item->active_cnt);
+ mutex_unlock(&cscfg_csdev_mutex);
Is there a guarantee that this item is active and present in the list after
we dropped the mutex above ? We could certainly nest the mutex as long as
we follow the order everywhere to prevent such a race.
Although removal not supported in this set, the rule is that nothing
can be removed while any configuration is active (count on
sys_active_cnt). - but a comment here could be added.
That said, given this is an atomic, not sure that the mutex is
necessary (I think previous versions did more than just update the
count), & perhaps the increment should be moved to the main
list_for_each loop.
quoted
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cscfg_activate_config);
+
+void cscfg_deactivate_config(unsigned long cfg_hash)
+{
+ struct cscfg_config_desc *curr_item, *match_item = 0;
+
+ mutex_lock(&cscfg_mutex);
+
+ list_for_each_entry(curr_item, &cscfg_mgr->data.config_desc_list, item) {
+ if ((unsigned long)curr_item->id_ea->var == cfg_hash) {
+ match_item = curr_item;
+ break;
+ }
+ }
+ mutex_unlock(&cscfg_mutex);
+ if (!match_item)
+ return;
+
+ dev_dbg(to_device_cscfg(), "Deactivate config %s.\n", match_item->name);
+
+ mutex_lock(&cscfg_csdev_mutex);
+ atomic_dec(&match_item->active_cnt);
+ mutex_unlock(&cscfg_csdev_mutex);
+
+ atomic_dec(&cscfg_mgr->data.sys_active_cnt);
+}
+EXPORT_SYMBOL_GPL(cscfg_deactivate_config);
+
+/* Find and program any active config for the supplied device.*/
+int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
+ unsigned long id_hash, int preset)
+{
+ struct cscfg_config_csdev *cfg = NULL, *item;
+ const struct cscfg_config_desc *desc;
+ int err = 0;
+
+ /* quickly check global count */
+ if (!atomic_read(&cscfg_mgr->data.sys_active_cnt))
+ return 0;
+
+ mutex_lock(&cscfg_csdev_mutex);
+ list_for_each_entry(item, &csdev->config_csdev_list, node) {
+ desc = item->desc;
+ if ((atomic_read(&desc->active_cnt)) &&
+ ((unsigned long)desc->id_ea->var == id_hash)) {
+ cfg = item;
+ break;
+ }
+ }
+ if (cfg) {
+ err = cscfg_csdev_enable_config(cfg, preset);
+ if (!err)
+ csdev->active_cfg_ctxt = (void *)cfg;
+ }
+ mutex_unlock(&cscfg_csdev_mutex);
+ return err;
+}
+EXPORT_SYMBOL_GPL(cscfg_csdev_enable_active_config);
+
+/* save and disable the active config for the device */
+void cscfg_csdev_disable_active_config(struct coresight_device *csdev)
+{
+ struct cscfg_config_csdev *cfg;
+
+ mutex_lock(&cscfg_csdev_mutex);
+ cfg = (struct cscfg_config_csdev *)csdev->active_cfg_ctxt;
+ if (cfg)
+ cscfg_csdev_disable_config(cfg);
+ mutex_unlock(&cscfg_csdev_mutex);
+}
+EXPORT_SYMBOL_GPL(cscfg_csdev_disable_active_config);
+
/* Initialise system configuration management device. */
struct device *to_device_cscfg(void)
nit: Is this aligned ? (It is from Patch 1, though).
quoted
* @config_desc_list: List of system configuration descriptors to load into registered devices.
- * @nr_csdev: Number of registered devices with the cscfg system
+ * @nr_csdev: Number of registered devices with the cscfg system
Spurious change ?
This struct disappears in the v5 respin, so the comments will too.
quoted
+ * @sys_active_cnt: Total number of active config descriptor references.
*/
struct cscfg_api_data {
struct list_head csdev_desc_list;
struct list_head feat_desc_list;
struct list_head config_desc_list;
int nr_csdev;
+ atomic_t sys_active_cnt;
};
/**
@@ -53,6 +55,12 @@ int cscfg_register_csdev(struct coresight_device *csdev, struct cscfg_match_desc *info, struct cscfg_csdev_feat_ops *ops); void cscfg_unregister_csdev(struct coresight_device *csdev);+int cscfg_activate_config(unsigned long cfg_hash);+void cscfg_deactivate_config(unsigned long cfg_hash);+void cscfg_csdev_reset_feats(struct coresight_device *csdev);+int cscfg_csdev_enable_active_config(struct coresight_device *csdev,+ unsigned long id_hash, int preset);+void cscfg_csdev_disable_active_config(struct coresight_device *csdev); /** * System configuration manager device.
@@ -245,6 +246,7 @@ struct coresight_device {/* system configuration and feature lists */structlist_headfeature_csdev_list;structlist_headconfig_csdev_list;+void*active_cfg_ctxt;};
Suzuki
Thanks for the review.
Mike
--
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
From: Mike Leach <hidden> Date: 2021-01-28 17:49:05
Loaded coresight configurations are registered in the cs_etm\cs_config sub
directory. This extends the etm-perf code to handle these registrations,
and the cs_syscfg driver to perform the registration on load.
Signed-off-by: Mike Leach <redacted>
---
.../hwtracing/coresight/coresight-config.h | 5 +-
.../hwtracing/coresight/coresight-etm-perf.c | 164 +++++++++++++++---
.../hwtracing/coresight/coresight-etm-perf.h | 8 +
.../hwtracing/coresight/coresight-syscfg.c | 13 +-
4 files changed, 166 insertions(+), 24 deletions(-)
@@ -32,8 +34,13 @@ PMU_FORMAT_ATTR(cycacc, "config:" __stringify(ETM_OPT_CYCACC));PMU_FORMAT_ATTR(contextid,"config:"__stringify(ETM_OPT_CTXTID));PMU_FORMAT_ATTR(timestamp,"config:"__stringify(ETM_OPT_TS));PMU_FORMAT_ATTR(retstack,"config:"__stringify(ETM_OPT_RETSTK));+/* preset - if sink ID is used as a configuration selector */+PMU_FORMAT_ATTR(preset,"config:0-3");/* Sink ID - same for all ETMs */PMU_FORMAT_ATTR(sinkid,"config2:0-31");+/* config ID - set if a system configuration is selected */+PMU_FORMAT_ATTR(configid,"config2:32-63");+staticstructattribute*etm_config_formats_attr[]={&format_attr_cycacc.attr,
@@ -219,7 +248,7 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,INIT_WORK(&event_data->work,free_event_data);/* First get the selected sink from user space. */-if(event->attr.config2){+if(event->attr.config2&GENMASK_ULL(31,0)){id=(u32)event->attr.config2;sink=coresight_get_sink_by_id(id);}
@@ -560,7 +585,6 @@ int etm_perf_add_symlink_sink(struct coresight_device *csdev)if(!ea)return-ENOMEM;-name=dev_name(dev);/* See function coresight_get_sink_by_id() to know where this is used */hash=hashlen_hash(hashlen_string(NULL,name));
@@ -574,31 +598,127 @@ int etm_perf_add_symlink_sink(struct coresight_device *csdev)ea->var=(unsignedlong*)hash;ret=sysfs_add_file_to_group(&pmu_dev->kobj,-&ea->attr.attr,"sinks");-+&ea->attr.attr,group_name);if(!ret)-csdev->ea=ea;-+*ext_attr=ea;returnret;}-voidetm_perf_del_symlink_sink(structcoresight_device*csdev)+intetm_perf_add_symlink_sink(structcoresight_device*csdev)+{+constchar*name;+structdevice*dev=&csdev->dev;++if(csdev->type!=CORESIGHT_DEV_TYPE_SINK&&+csdev->type!=CORESIGHT_DEV_TYPE_LINKSINK)+return-EINVAL;++if(csdev->ea!=NULL)+return-EINVAL;++name=dev_name(dev);+returnetm_perf_add_symlink_group(dev,&csdev->ea,name,"sinks");+}++voidetm_perf_del_symlink_group(structdev_ext_attribute*ea,constchar*group_name){structdevice*pmu_dev=etm_pmu.dev;-structdev_ext_attribute*ea=csdev->ea;+sysfs_remove_file_from_group(&pmu_dev->kobj,+&ea->attr.attr,group_name);+}++voidetm_perf_del_symlink_sink(structcoresight_device*csdev)+{if(csdev->type!=CORESIGHT_DEV_TYPE_SINK&&csdev->type!=CORESIGHT_DEV_TYPE_LINKSINK)return;-if(!ea)+if(!csdev->ea)return;-sysfs_remove_file_from_group(&pmu_dev->kobj,-&ea->attr.attr,"sinks");+etm_perf_del_symlink_group(csdev->ea,"sinks");csdev->ea=NULL;}+/* string to contain the attribute value */+#define CSCFG_EVENT_STR_SIZE 32++staticssize_tetm_perf_cscfg_event_show(structdevice*dev,+structdevice_attribute*dattr,+char*buf)+{+structdev_ext_attribute*ea;++ea=container_of(dattr,structdev_ext_attribute,attr);+returnscnprintf(buf,PAGE_SIZE,"%s\n",(constchar*)(ea->var));+}++staticintetm_perf_add_cscfg_event(structdevice*dev,structcscfg_config_desc*cs_cfg)+{+structdev_ext_attribute*ea;+unsignedlonghash;+intret;+structdevice*pmu_dev=etm_pmu.dev;++ea=devm_kzalloc(dev,sizeof(*ea),GFP_KERNEL);+if(!ea)+return-ENOMEM;++hash=(unsignedlong)cs_cfg->id_ea->var;++sysfs_attr_init(&ea->attr.attr);+ea->attr.attr.name=devm_kstrdup(dev,cs_cfg->name,GFP_KERNEL);+if(!ea->attr.attr.name)+return-ENOMEM;++/*+*attributevalueis"configid=<hash>".+*thiswillbewhatperfevaluateswhentheconfignameisused+*onthecommandline.+*/+ea->var=devm_kzalloc(dev,CSCFG_EVENT_STR_SIZE,GFP_KERNEL);+if(!ea->var)+return-ENOMEM;++scnprintf(ea->var,CSCFG_EVENT_STR_SIZE,"configid=0x%lx",hash);+ea->attr.attr.mode=0444;+ea->attr.show=etm_perf_cscfg_event_show;++ret=sysfs_add_file_to_group(&pmu_dev->kobj,+&ea->attr.attr,"events");+if(!ret)+cs_cfg->event_ea=ea;+returnret;+}++intetm_perf_add_symlink_cscfg(structdevice*dev,structcscfg_config_desc*cs_cfg)+{+interr;++if(cs_cfg->id_ea!=NULL)+return0;++err=etm_perf_add_symlink_group(dev,&cs_cfg->id_ea,+cs_cfg->name,"configurations");++if(!err)+err=etm_perf_add_cscfg_event(dev,cs_cfg);++returnerr;+}++voidetm_perf_del_symlink_cscfg(structcscfg_config_desc*cs_cfg)+{+if(!cs_cfg->id_ea)+return;++etm_perf_del_symlink_group(cs_cfg->id_ea,"configurations");+etm_perf_del_symlink_group(cs_cfg->event_ea,"events");+cs_cfg->id_ea=NULL;+cs_cfg->event_ea=NULL;+}+int__initetm_perf_init(void){intret;
On Thu, Jan 28, 2021 at 05:09:30PM +0000, Mike Leach wrote:
quoted hunk
Loaded coresight configurations are registered in the cs_etm\cs_config sub
directory. This extends the etm-perf code to handle these registrations,
and the cs_syscfg driver to perform the registration on load.
Signed-off-by: Mike Leach <redacted>
---
.../hwtracing/coresight/coresight-config.h | 5 +-
.../hwtracing/coresight/coresight-etm-perf.c | 164 +++++++++++++++---
.../hwtracing/coresight/coresight-etm-perf.h | 8 +
.../hwtracing/coresight/coresight-syscfg.c | 13 +-
4 files changed, 166 insertions(+), 24 deletions(-)
@@ -32,8 +34,13 @@ PMU_FORMAT_ATTR(cycacc, "config:" __stringify(ETM_OPT_CYCACC));PMU_FORMAT_ATTR(contextid,"config:"__stringify(ETM_OPT_CTXTID));PMU_FORMAT_ATTR(timestamp,"config:"__stringify(ETM_OPT_TS));PMU_FORMAT_ATTR(retstack,"config:"__stringify(ETM_OPT_RETSTK));+/* preset - if sink ID is used as a configuration selector */+PMU_FORMAT_ATTR(preset,"config:0-3");/* Sink ID - same for all ETMs */PMU_FORMAT_ATTR(sinkid,"config2:0-31");+/* config ID - set if a system configuration is selected */+PMU_FORMAT_ATTR(configid,"config2:32-63");+staticstructattribute*etm_config_formats_attr[]={&format_attr_cycacc.attr,
@@ -219,7 +248,7 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,INIT_WORK(&event_data->work,free_event_data);/* First get the selected sink from user space. */-if(event->attr.config2){+if(event->attr.config2&GENMASK_ULL(31,0)){id=(u32)event->attr.config2;sink=coresight_get_sink_by_id(id);}
@@ -560,7 +585,6 @@ int etm_perf_add_symlink_sink(struct coresight_device *csdev) if (!ea) return -ENOMEM;- name = dev_name(dev); /* See function coresight_get_sink_by_id() to know where this is used */
I would also update this comment. If @name is a sink then the hash will be
used in coresight_get_sink_by_id(), and if it is a configuration it will be used
in etm_perf_add_cscfg_event() and cscfg_activate_config().
quoted hunk
hash = hashlen_hash(hashlen_string(NULL, name));
@@ -574,31 +598,127 @@ int etm_perf_add_symlink_sink(struct coresight_device *csdev) ea->var = (unsigned long *)hash; ret = sysfs_add_file_to_group(&pmu_dev->kobj,- &ea->attr.attr, "sinks");-+ &ea->attr.attr, group_name); if (!ret)- csdev->ea = ea;-+ *ext_attr = ea; return ret; }-void etm_perf_del_symlink_sink(struct coresight_device *csdev)+int etm_perf_add_symlink_sink(struct coresight_device *csdev)+{+ const char *name;+ struct device *dev = &csdev->dev;++ if (csdev->type != CORESIGHT_DEV_TYPE_SINK &&+ csdev->type != CORESIGHT_DEV_TYPE_LINKSINK)+ return -EINVAL;++ if (csdev->ea != NULL)+ return -EINVAL;++ name = dev_name(dev);+ return etm_perf_add_symlink_group(dev, &csdev->ea, name, "sinks");+}++void etm_perf_del_symlink_group(struct dev_ext_attribute *ea, const char *group_name) { struct device *pmu_dev = etm_pmu.dev;- struct dev_ext_attribute *ea = csdev->ea;+ sysfs_remove_file_from_group(&pmu_dev->kobj,+ &ea->attr.attr, group_name);+}++void etm_perf_del_symlink_sink(struct coresight_device *csdev)+{ if (csdev->type != CORESIGHT_DEV_TYPE_SINK && csdev->type != CORESIGHT_DEV_TYPE_LINKSINK) return;- if (!ea)+ if (!csdev->ea) return;- sysfs_remove_file_from_group(&pmu_dev->kobj,- &ea->attr.attr, "sinks");+ etm_perf_del_symlink_group(csdev->ea, "sinks"); csdev->ea = NULL; }+/* string to contain the attribute value */+#define CSCFG_EVENT_STR_SIZE 32++static ssize_t etm_perf_cscfg_event_show(struct device *dev,+ struct device_attribute *dattr,+ char *buf)+{+ struct dev_ext_attribute *ea;++ ea = container_of(dattr, struct dev_ext_attribute, attr);+ return scnprintf(buf, PAGE_SIZE, "%s\n", (const char *)(ea->var));+}++static int etm_perf_add_cscfg_event(struct device *dev, struct cscfg_config_desc *cs_cfg)+{+ struct dev_ext_attribute *ea;+ unsigned long hash;+ int ret;+ struct device *pmu_dev = etm_pmu.dev;++ ea = devm_kzalloc(dev, sizeof(*ea), GFP_KERNEL);+ if (!ea)+ return -ENOMEM;++ hash = (unsigned long)cs_cfg->id_ea->var;++ sysfs_attr_init(&ea->attr.attr);+ ea->attr.attr.name = devm_kstrdup(dev, cs_cfg->name, GFP_KERNEL);+ if (!ea->attr.attr.name)+ return -ENOMEM;++ /*+ * attribute value is "configid=<hash>".+ * this will be what perf evaluates when the config name is used+ * on the command line.+ */+ ea->var = devm_kzalloc(dev, CSCFG_EVENT_STR_SIZE, GFP_KERNEL);+ if (!ea->var)+ return -ENOMEM;++ scnprintf(ea->var, CSCFG_EVENT_STR_SIZE, "configid=0x%lx", hash);+ ea->attr.attr.mode = 0444;+ ea->attr.show = etm_perf_cscfg_event_show;++ ret = sysfs_add_file_to_group(&pmu_dev->kobj,+ &ea->attr.attr, "events");+ if (!ret)+ cs_cfg->event_ea = ea;+ return ret;+}++int etm_perf_add_symlink_cscfg(struct device *dev, struct cscfg_config_desc *cs_cfg)+{+ int err;++ if (cs_cfg->id_ea != NULL)+ return 0;++ err = etm_perf_add_symlink_group(dev, &cs_cfg->id_ea,+ cs_cfg->name, "configurations");
Do we need configurations to be advertised under
/sys/bus/event_source/devices/cs_etm given that they are already found in
/sys/kernel/config/coresight-syscfg? And the events already carry the hash if
someone is really keen using the "configid=" syntax.
In my opinion we can get by with what is in configfs and do away with the
"configurations" directory here.
+
+ if (!err)
+ err = etm_perf_add_cscfg_event(dev, cs_cfg);
+
From: Mike Leach <hidden> Date: 2021-02-26 19:27:34
HI Mathieu.
On Wed, 24 Feb 2021 at 18:33, Mathieu Poirier
[off-list ref] wrote:
On Thu, Jan 28, 2021 at 05:09:30PM +0000, Mike Leach wrote:
quoted
Loaded coresight configurations are registered in the cs_etm\cs_config sub
directory. This extends the etm-perf code to handle these registrations,
and the cs_syscfg driver to perform the registration on load.
Signed-off-by: Mike Leach <redacted>
---
.../hwtracing/coresight/coresight-config.h | 5 +-
.../hwtracing/coresight/coresight-etm-perf.c | 164 +++++++++++++++---
.../hwtracing/coresight/coresight-etm-perf.h | 8 +
.../hwtracing/coresight/coresight-syscfg.c | 13 +-
4 files changed, 166 insertions(+), 24 deletions(-)
@@ -32,8 +34,13 @@ PMU_FORMAT_ATTR(cycacc, "config:" __stringify(ETM_OPT_CYCACC));PMU_FORMAT_ATTR(contextid,"config:"__stringify(ETM_OPT_CTXTID));PMU_FORMAT_ATTR(timestamp,"config:"__stringify(ETM_OPT_TS));PMU_FORMAT_ATTR(retstack,"config:"__stringify(ETM_OPT_RETSTK));+/* preset - if sink ID is used as a configuration selector */+PMU_FORMAT_ATTR(preset,"config:0-3");/* Sink ID - same for all ETMs */PMU_FORMAT_ATTR(sinkid,"config2:0-31");+/* config ID - set if a system configuration is selected */+PMU_FORMAT_ATTR(configid,"config2:32-63");+staticstructattribute*etm_config_formats_attr[]={&format_attr_cycacc.attr,
@@ -219,7 +248,7 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,INIT_WORK(&event_data->work,free_event_data);/* First get the selected sink from user space. */-if(event->attr.config2){+if(event->attr.config2&GENMASK_ULL(31,0)){id=(u32)event->attr.config2;sink=coresight_get_sink_by_id(id);}
@@ -560,7 +585,6 @@ int etm_perf_add_symlink_sink(struct coresight_device *csdev) if (!ea) return -ENOMEM;- name = dev_name(dev); /* See function coresight_get_sink_by_id() to know where this is used */
I would also update this comment. If @name is a sink then the hash will be
used in coresight_get_sink_by_id(), and if it is a configuration it will be used
in etm_perf_add_cscfg_event() and cscfg_activate_config().
OK.
quoted
hash = hashlen_hash(hashlen_string(NULL, name));
@@ -574,31 +598,127 @@ int etm_perf_add_symlink_sink(struct coresight_device *csdev) ea->var = (unsigned long *)hash; ret = sysfs_add_file_to_group(&pmu_dev->kobj,- &ea->attr.attr, "sinks");-+ &ea->attr.attr, group_name); if (!ret)- csdev->ea = ea;-+ *ext_attr = ea; return ret; }-void etm_perf_del_symlink_sink(struct coresight_device *csdev)+int etm_perf_add_symlink_sink(struct coresight_device *csdev)+{+ const char *name;+ struct device *dev = &csdev->dev;++ if (csdev->type != CORESIGHT_DEV_TYPE_SINK &&+ csdev->type != CORESIGHT_DEV_TYPE_LINKSINK)+ return -EINVAL;++ if (csdev->ea != NULL)+ return -EINVAL;++ name = dev_name(dev);+ return etm_perf_add_symlink_group(dev, &csdev->ea, name, "sinks");+}++void etm_perf_del_symlink_group(struct dev_ext_attribute *ea, const char *group_name) { struct device *pmu_dev = etm_pmu.dev;- struct dev_ext_attribute *ea = csdev->ea;+ sysfs_remove_file_from_group(&pmu_dev->kobj,+ &ea->attr.attr, group_name);+}++void etm_perf_del_symlink_sink(struct coresight_device *csdev)+{ if (csdev->type != CORESIGHT_DEV_TYPE_SINK && csdev->type != CORESIGHT_DEV_TYPE_LINKSINK) return;- if (!ea)+ if (!csdev->ea) return;- sysfs_remove_file_from_group(&pmu_dev->kobj,- &ea->attr.attr, "sinks");+ etm_perf_del_symlink_group(csdev->ea, "sinks"); csdev->ea = NULL; }+/* string to contain the attribute value */+#define CSCFG_EVENT_STR_SIZE 32++static ssize_t etm_perf_cscfg_event_show(struct device *dev,+ struct device_attribute *dattr,+ char *buf)+{+ struct dev_ext_attribute *ea;++ ea = container_of(dattr, struct dev_ext_attribute, attr);+ return scnprintf(buf, PAGE_SIZE, "%s\n", (const char *)(ea->var));+}++static int etm_perf_add_cscfg_event(struct device *dev, struct cscfg_config_desc *cs_cfg)+{+ struct dev_ext_attribute *ea;+ unsigned long hash;+ int ret;+ struct device *pmu_dev = etm_pmu.dev;++ ea = devm_kzalloc(dev, sizeof(*ea), GFP_KERNEL);+ if (!ea)+ return -ENOMEM;++ hash = (unsigned long)cs_cfg->id_ea->var;++ sysfs_attr_init(&ea->attr.attr);+ ea->attr.attr.name = devm_kstrdup(dev, cs_cfg->name, GFP_KERNEL);+ if (!ea->attr.attr.name)+ return -ENOMEM;++ /*+ * attribute value is "configid=<hash>".+ * this will be what perf evaluates when the config name is used+ * on the command line.+ */+ ea->var = devm_kzalloc(dev, CSCFG_EVENT_STR_SIZE, GFP_KERNEL);+ if (!ea->var)+ return -ENOMEM;++ scnprintf(ea->var, CSCFG_EVENT_STR_SIZE, "configid=0x%lx", hash);+ ea->attr.attr.mode = 0444;+ ea->attr.show = etm_perf_cscfg_event_show;++ ret = sysfs_add_file_to_group(&pmu_dev->kobj,+ &ea->attr.attr, "events");+ if (!ret)+ cs_cfg->event_ea = ea;+ return ret;+}++int etm_perf_add_symlink_cscfg(struct device *dev, struct cscfg_config_desc *cs_cfg)+{+ int err;++ if (cs_cfg->id_ea != NULL)+ return 0;++ err = etm_perf_add_symlink_group(dev, &cs_cfg->id_ea,+ cs_cfg->name, "configurations");
Do we need configurations to be advertised under
/sys/bus/event_source/devices/cs_etm given that they are already found in
/sys/kernel/config/coresight-syscfg? And the events already carry the hash if
someone is really keen using the "configid=" syntax.
In my opinion we can get by with what is in configfs and do away with the
"configurations" directory here.
Agreed - since stuff is now in events then this does become redundant.
quoted
+
+ if (!err)
+ err = etm_perf_add_cscfg_event(dev, cs_cfg);
+
Thanks
Mike
--
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
From: Suzuki K Poulose <suzuki.poulose@arm.com> Date: 2021-03-04 12:15:28
On 1/28/21 5:09 PM, Mike Leach wrote:
quoted hunk
Loaded coresight configurations are registered in the cs_etm\cs_config sub
directory. This extends the etm-perf code to handle these registrations,
and the cs_syscfg driver to perform the registration on load.
Signed-off-by: Mike Leach <redacted>
---
.../hwtracing/coresight/coresight-config.h | 5 +-
.../hwtracing/coresight/coresight-etm-perf.c | 164 +++++++++++++++---
.../hwtracing/coresight/coresight-etm-perf.h | 8 +
.../hwtracing/coresight/coresight-syscfg.c | 13 +-
4 files changed, 166 insertions(+), 24 deletions(-)
@@ -32,8 +34,13 @@ PMU_FORMAT_ATTR(cycacc, "config:" __stringify(ETM_OPT_CYCACC));PMU_FORMAT_ATTR(contextid,"config:"__stringify(ETM_OPT_CTXTID));PMU_FORMAT_ATTR(timestamp,"config:"__stringify(ETM_OPT_TS));PMU_FORMAT_ATTR(retstack,"config:"__stringify(ETM_OPT_RETSTK));+/* preset - if sink ID is used as a configuration selector */+PMU_FORMAT_ATTR(preset,"config:0-3");/* Sink ID - same for all ETMs */PMU_FORMAT_ATTR(sinkid,"config2:0-31");+/* config ID - set if a system configuration is selected */+PMU_FORMAT_ATTR(configid,"config2:32-63");+staticstructattribute*etm_config_formats_attr[]={&format_attr_cycacc.attr,
@@ -219,7 +248,7 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,INIT_WORK(&event_data->work,free_event_data);/* First get the selected sink from user space. */-if(event->attr.config2){+if(event->attr.config2&GENMASK_ULL(31,0)){id=(u32)event->attr.config2;sink=coresight_get_sink_by_id(id);}
Couple of nits:
This could be:
struct dev_ext_attribute *
etm_perf_add_to_group_hashed(struct device *dev,
const char *group,
const char *name)
{
}
This could return the ea on success avoiding the **ext_attr as argument.
Also the name of the function indicates what it does.
@@ -560,7 +585,6 @@ int etm_perf_add_symlink_sink(struct coresight_device *csdev) if (!ea) return -ENOMEM;- name = dev_name(dev); /* See function coresight_get_sink_by_id() to know where this is used */ hash = hashlen_hash(hashlen_string(NULL, name));
@@ -574,31 +598,127 @@ int etm_perf_add_symlink_sink(struct coresight_device *csdev) ea->var = (unsigned long *)hash; ret = sysfs_add_file_to_group(&pmu_dev->kobj,- &ea->attr.attr, "sinks");-+ &ea->attr.attr, group_name); if (!ret)- csdev->ea = ea;-+ *ext_attr = ea; return ret;
From: Mike Leach <hidden> Date: 2021-03-04 14:20:50
Hi Suzuki,
On Thu, 4 Mar 2021 at 12:13, Suzuki K Poulose [off-list ref] wrote:
On 1/28/21 5:09 PM, Mike Leach wrote:
quoted
Loaded coresight configurations are registered in the cs_etm\cs_config sub
directory. This extends the etm-perf code to handle these registrations,
and the cs_syscfg driver to perform the registration on load.
Signed-off-by: Mike Leach <redacted>
---
.../hwtracing/coresight/coresight-config.h | 5 +-
.../hwtracing/coresight/coresight-etm-perf.c | 164 +++++++++++++++---
.../hwtracing/coresight/coresight-etm-perf.h | 8 +
.../hwtracing/coresight/coresight-syscfg.c | 13 +-
4 files changed, 166 insertions(+), 24 deletions(-)
@@ -32,8 +34,13 @@ PMU_FORMAT_ATTR(cycacc, "config:" __stringify(ETM_OPT_CYCACC));PMU_FORMAT_ATTR(contextid,"config:"__stringify(ETM_OPT_CTXTID));PMU_FORMAT_ATTR(timestamp,"config:"__stringify(ETM_OPT_TS));PMU_FORMAT_ATTR(retstack,"config:"__stringify(ETM_OPT_RETSTK));+/* preset - if sink ID is used as a configuration selector */+PMU_FORMAT_ATTR(preset,"config:0-3");/* Sink ID - same for all ETMs */PMU_FORMAT_ATTR(sinkid,"config2:0-31");+/* config ID - set if a system configuration is selected */+PMU_FORMAT_ATTR(configid,"config2:32-63");+staticstructattribute*etm_config_formats_attr[]={&format_attr_cycacc.attr,
@@ -219,7 +248,7 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,INIT_WORK(&event_data->work,free_event_data);/* First get the selected sink from user space. */-if(event->attr.config2){+if(event->attr.config2&GENMASK_ULL(31,0)){id=(u32)event->attr.config2;sink=coresight_get_sink_by_id(id);}
Couple of nits:
This could be:
struct dev_ext_attribute *
etm_perf_add_to_group_hashed(struct device *dev,
const char *group,
const char *name)
{
}
This could return the ea on success avoiding the **ext_attr as argument.
Also the name of the function indicates what it does.
@@ -560,7 +585,6 @@ int etm_perf_add_symlink_sink(struct coresight_device *csdev) if (!ea) return -ENOMEM;- name = dev_name(dev); /* See function coresight_get_sink_by_id() to know where this is used */ hash = hashlen_hash(hashlen_string(NULL, name));
@@ -574,31 +598,127 @@ int etm_perf_add_symlink_sink(struct coresight_device *csdev) ea->var = (unsigned long *)hash; ret = sysfs_add_file_to_group(&pmu_dev->kobj,- &ea->attr.attr, "sinks");-+ &ea->attr.attr, group_name); if (!ret)- csdev->ea = ea;-+ *ext_attr = ea; return ret;
ea->var _is_ "configid=0x%lx" due to the way perf handles the events
sub-dir entries.
quoted
+
+static int etm_perf_add_cscfg_event(struct device *dev, struct cscfg_config_desc *cs_cfg)
+{
+ struct dev_ext_attribute *ea;
+ unsigned long hash;
+ int ret;
+ struct device *pmu_dev = etm_pmu.dev;
+
+ ea = devm_kzalloc(dev, sizeof(*ea), GFP_KERNEL);
+ if (!ea)
+ return -ENOMEM;
+
+ hash = (unsigned long)cs_cfg->id_ea->var;
+
+ sysfs_attr_init(&ea->attr.attr);
+ ea->attr.attr.name = devm_kstrdup(dev, cs_cfg->name, GFP_KERNEL);
+ if (!ea->attr.attr.name)
+ return -ENOMEM;
+
+ /*
+ * attribute value is "configid=<hash>".
+ * this will be what perf evaluates when the config name is used
+ * on the command line.
+ */
+ ea->var = devm_kzalloc(dev, CSCFG_EVENT_STR_SIZE, GFP_KERNEL);
+ if (!ea->var)
+ return -ENOMEM;
Could we drop this string and use the "hash" instead ?
No. My understanding is that we have added an events directory to
cs_etm, and add the configurations in there:-
cs_etm/events/autofdo
Now the contents of autofdo are "configid=0x<hash-value>" - where
hash-value is the hash of "autofdo".
On the perf command line:-
perf record -e cs_etm/autofdo/ .....
will result in perf parsing autofdo, looking in the events dir for
cs_etm, seeing the configid=-string, and parsing that to assign to
configid attribute - which we have allocated to config2:63:32 - this
will then appear as a value in the perf_event and we can load the
configuration when starting up the event on the ETM etc.
--
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
From: Suzuki K Poulose <suzuki.poulose@arm.com> Date: 2021-03-04 14:26:59
On 3/4/21 2:19 PM, Mike Leach wrote:
Hi Suzuki,
On Thu, 4 Mar 2021 at 12:13, Suzuki K Poulose [off-list ref] wrote:
quoted
On 1/28/21 5:09 PM, Mike Leach wrote:
quoted
Loaded coresight configurations are registered in the cs_etm\cs_config sub
directory. This extends the etm-perf code to handle these registrations,
and the cs_syscfg driver to perform the registration on load.
Signed-off-by: Mike Leach <redacted>
---
.../hwtracing/coresight/coresight-config.h | 5 +-
.../hwtracing/coresight/coresight-etm-perf.c | 164 +++++++++++++++---
.../hwtracing/coresight/coresight-etm-perf.h | 8 +
.../hwtracing/coresight/coresight-syscfg.c | 13 +-
4 files changed, 166 insertions(+), 24 deletions(-)
ea->var _is_ "configid=0x%lx" due to the way perf handles the events
sub-dir entries.
This must be combined with the suggestion below.
quoted
quoted
+
+static int etm_perf_add_cscfg_event(struct device *dev, struct cscfg_config_desc *cs_cfg)
+{
+ struct dev_ext_attribute *ea;
+ unsigned long hash;
+ int ret;
+ struct device *pmu_dev = etm_pmu.dev;
+
+ ea = devm_kzalloc(dev, sizeof(*ea), GFP_KERNEL);
+ if (!ea)
+ return -ENOMEM;
+
+ hash = (unsigned long)cs_cfg->id_ea->var;
+
+ sysfs_attr_init(&ea->attr.attr);
+ ea->attr.attr.name = devm_kstrdup(dev, cs_cfg->name, GFP_KERNEL);
+ if (!ea->attr.attr.name)
+ return -ENOMEM;
+
+ /*
+ * attribute value is "configid=<hash>".
+ * this will be what perf evaluates when the config name is used
+ * on the command line.
+ */
+ ea->var = devm_kzalloc(dev, CSCFG_EVENT_STR_SIZE, GFP_KERNEL);
+ if (!ea->var)
+ return -ENOMEM;
Could we drop this string and use the "hash" instead ?
No. My understanding is that we have added an events directory to
cs_etm, and add the configurations in there:-
cs_etm/events/autofdo
Now the contents of autofdo are "configid=0x<hash-value>" - where
hash-value is the hash of "autofdo".
On the perf command line:-
perf record -e cs_etm/autofdo/ .....
will result in perf parsing autofdo, looking in the events dir for
cs_etm, seeing the configid=-string, and parsing that to assign to
configid attribute - which we have allocated to config2:63:32 - this
will then appear as a value in the perf_event and we can load the
configuration when starting up the event on the ETM etc.
Sorry, I was not explicit in my comments. You could drop the string and
have ea->var = hash. And the _show() could simply do
"configid=0x%lx" , hash
as mentioned above.
That would avoid another string allocation, with the same interface.
Suzuki
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
From: Mike Leach <hidden> Date: 2021-03-04 14:47:48
Hi
On Thu, 4 Mar 2021 at 14:25, Suzuki K Poulose [off-list ref] wrote:
On 3/4/21 2:19 PM, Mike Leach wrote:
quoted
Hi Suzuki,
On Thu, 4 Mar 2021 at 12:13, Suzuki K Poulose [off-list ref] wrote:
quoted
On 1/28/21 5:09 PM, Mike Leach wrote:
quoted
Loaded coresight configurations are registered in the cs_etm\cs_config sub
directory. This extends the etm-perf code to handle these registrations,
and the cs_syscfg driver to perform the registration on load.
Signed-off-by: Mike Leach <redacted>
---
.../hwtracing/coresight/coresight-config.h | 5 +-
.../hwtracing/coresight/coresight-etm-perf.c | 164 +++++++++++++++---
.../hwtracing/coresight/coresight-etm-perf.h | 8 +
.../hwtracing/coresight/coresight-syscfg.c | 13 +-
4 files changed, 166 insertions(+), 24 deletions(-)
ea->var _is_ "configid=0x%lx" due to the way perf handles the events
sub-dir entries.
This must be combined with the suggestion below.
quoted
quoted
quoted
+
+static int etm_perf_add_cscfg_event(struct device *dev, struct cscfg_config_desc *cs_cfg)
+{
+ struct dev_ext_attribute *ea;
+ unsigned long hash;
+ int ret;
+ struct device *pmu_dev = etm_pmu.dev;
+
+ ea = devm_kzalloc(dev, sizeof(*ea), GFP_KERNEL);
+ if (!ea)
+ return -ENOMEM;
+
+ hash = (unsigned long)cs_cfg->id_ea->var;
+
+ sysfs_attr_init(&ea->attr.attr);
+ ea->attr.attr.name = devm_kstrdup(dev, cs_cfg->name, GFP_KERNEL);
+ if (!ea->attr.attr.name)
+ return -ENOMEM;
+
+ /*
+ * attribute value is "configid=<hash>".
+ * this will be what perf evaluates when the config name is used
+ * on the command line.
+ */
+ ea->var = devm_kzalloc(dev, CSCFG_EVENT_STR_SIZE, GFP_KERNEL);
+ if (!ea->var)
+ return -ENOMEM;
Could we drop this string and use the "hash" instead ?
No. My understanding is that we have added an events directory to
cs_etm, and add the configurations in there:-
cs_etm/events/autofdo
Now the contents of autofdo are "configid=0x<hash-value>" - where
hash-value is the hash of "autofdo".
On the perf command line:-
perf record -e cs_etm/autofdo/ .....
will result in perf parsing autofdo, looking in the events dir for
cs_etm, seeing the configid=-string, and parsing that to assign to
configid attribute - which we have allocated to config2:63:32 - this
will then appear as a value in the perf_event and we can load the
configuration when starting up the event on the ETM etc.
Sorry, I was not explicit in my comments. You could drop the string and
have ea->var = hash. And the _show() could simply do
"configid=0x%lx" , hash
as mentioned above.
That would avoid another string allocation, with the same interface.
OK, that makes sense.
Mike
Suzuki
--
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
From: Mike Leach <hidden> Date: 2021-01-28 17:50:22
API for individual devices to register with the syscfg management
system is added.
Devices register with matching information, and any features or
configurations that match will be loaded into the device.
The feature and configuration loading is extended so that on load these
are loaded into any currently registered devices. This allows
configuration loading after devices have been registered.
Signed-off-by: Mike Leach <redacted>
---
.../hwtracing/coresight/coresight-config.h | 98 +++++
.../hwtracing/coresight/coresight-syscfg.c | 348 ++++++++++++++++++
.../hwtracing/coresight/coresight-syscfg.h | 20 +
include/linux/coresight.h | 5 +
4 files changed, 471 insertions(+)
@@ -25,6 +25,212 @@ static struct cscfg_manager *cscfg_mgr;/* load features and configuations into the lists */+/* protect the cfg lists in the csdev instances */+staticDEFINE_MUTEX(cscfg_csdev_mutex);++/* get name feature instance from a coresight device list of features */+staticstructcscfg_feature_csdev*+cscfg_get_feat_csdev(structcoresight_device*csdev,constchar*name)+{+structcscfg_feature_csdev*feat=NULL;++list_for_each_entry(feat,&csdev->feature_csdev_list,node){+if(strcmp(feat->desc->name,name)==0)+returnfeat;+}+returnNULL;+}++/* allocate the device config instance - with max number of used features */+staticstructcscfg_config_csdev*+cscfg_alloc_csdev_cfg(structcoresight_device*csdev,intnr_feats)+{+structcscfg_config_csdev*dev_cfg=NULL;+structdevice*dev=csdev->dev.parent;++/* this is being allocated using the devm for the coresight device */+dev_cfg=devm_kzalloc(dev,sizeof(structcscfg_config_csdev),GFP_KERNEL);+if(!dev_cfg)+returnNULL;++dev_cfg->csdev=csdev;+dev_cfg->feats=devm_kcalloc(dev,nr_feats,+sizeof(structcscfg_feature_csdev*),+GFP_KERNEL);+if(!dev_cfg->feats)+dev_cfg=NULL;+returndev_cfg;+}++/* check match info between used feature from the config and a regisered device */+staticboolcscfg_match_feat_info(structcscfg_match_desc*used_cmp,+structcscfg_match_desc*reg_dev)+{+/* if flags don't match then fail early */+if(!(used_cmp->match_flags®_dev->match_flags))+returnfalse;++returntrue;+}++/* Load a config into a device if there are feature matches between config and device */+staticintcscfg_add_csdev_cfg(structcoresight_device*csdev,+structcscfg_match_desc*match_info,+structcscfg_config_desc*cfg_desc)+{+structcscfg_config_csdev*dev_cfg=NULL;+structcscfg_config_feat_ref*feat_ref;+structcscfg_feature_csdev*feat;+intchecked;++/* look at each required feature and see if it matches any feature on the device */+for(checked=0;checked<cfg_desc->nr_refs;checked++){+feat_ref=&cfg_desc->refs[checked];+if(cscfg_match_feat_info(&feat_ref->match,match_info)){+/* device matched - get the feature */+feat=cscfg_get_feat_csdev(csdev,feat_ref->name);+if(!feat)+return-EINVAL;+if(!dev_cfg){+dev_cfg=cscfg_alloc_csdev_cfg(csdev,cfg_desc->nr_refs);+if(!dev_cfg)+return-ENOMEM;+dev_cfg->desc=cfg_desc;+}+dev_cfg->feats[dev_cfg->nr_feat++]=feat;+}+}+/* if matched features, add config to device.*/+if(dev_cfg){+mutex_lock(&cscfg_csdev_mutex);+list_add(&dev_cfg->node,&csdev->config_csdev_list);+mutex_unlock(&cscfg_csdev_mutex);+}++return0;+}++/*+*Addtheconfigtothesetofregistereddevices-callwithmutexlocked.+*Iteratesthroughdevices-anydevicethatmatchesoneormoreofthe+*configurationfeatureswillloadit,theotherswillignoreit.+*/+staticintcscfg_add_cfg_to_csdevs(structcscfg_config_desc*cfg_desc)+{+structcscfg_csdev_register*curr_item;+interr;++list_for_each_entry(curr_item,&cscfg_mgr->data.csdev_desc_list,item){+err=cscfg_add_csdev_cfg(curr_item->csdev,&curr_item->match_info,cfg_desc);+if(err)+returnerr;+}+return0;+}++/*+*Allocateafeatureobjectforloadintoacsdev.+*memoryallocatedusingthecsdev->devobjectusingdevmmanagedallocator.+*/+staticstructcscfg_feature_csdev*+cscfg_alloc_csdev_feat(structcoresight_device*csdev,structcscfg_feature_desc*feat_desc)+{+structcscfg_feature_csdev*feat=NULL;+structdevice*dev=csdev->dev.parent;+inti;++feat=devm_kzalloc(dev,sizeof(structcscfg_feature_csdev),GFP_KERNEL);+if(!feat)+returnNULL;++/* parameters are optional - could be 0 */+feat->nr_params=feat_desc->nr_params;++/*+*ifweneedparameters,zeroallocthespacehere,theloadroutinein+*thecsdevdevicedriverwillfilloutsomeinformationaccordingto+*featuredescriptor.+*/+if(feat->nr_params){+feat->params=devm_kcalloc(dev,feat->nr_params,+sizeof(structcscfg_parameter_csdev),+GFP_KERNEL);+if(!feat->params)+returnNULL;++/*+*fillinthefeaturereferenceintheparam-otherfields+*handledbyloaderincsdev.+*/+for(i=0;i<feat->nr_params;i++)+feat->params[i].feat=feat;+}++/*+*Alwayshaveregisterstoprogram-againtheloadroutineincsdevdevice+*willfilloutaccordingtofeaturedescriptoranddevicerequirements.+*/+feat->nr_regs=feat_desc->nr_regs;+feat->regs=devm_kcalloc(dev,feat->nr_regs,+sizeof(structcscfg_reg_csdev),GFP_KERNEL);+if(!feat->regs)+returnNULL;++/* load the feature default values */+feat->desc=feat_desc;+feat->csdev=csdev;++returnfeat;+}++/* load one feature into one coresight device */+staticintcscfg_load_feat_csdev(structcoresight_device*csdev,+structcscfg_feature_desc*feat_desc,+structcscfg_csdev_feat_ops*ops)+{+structcscfg_feature_csdev*feat_csdev;+interr;++if(!ops->load_feat)+return-EINVAL;++feat_csdev=cscfg_alloc_csdev_feat(csdev,feat_desc);+if(!feat_csdev)+return-ENOMEM;++/* load the feature into the device - may modify default ops*/+err=ops->load_feat(csdev,feat_csdev);+if(err)+returnerr;++/* add to internal csdev feature list */+mutex_lock(&cscfg_csdev_mutex);+list_add(&feat_csdev->node,&csdev->feature_csdev_list);+mutex_unlock(&cscfg_csdev_mutex);++return0;+}++/*+*Addfeaturetoanymatchingdevices-callwithmutexlocked.+*Iteratesthroughdevices-anydevicethatmatchesthefeaturewillbe+*calledtoloadit.+*/+staticintcscfg_add_feat_to_csdevs(structcscfg_feature_desc*feat_desc)+{+structcscfg_csdev_register*curr_item;+interr;++list_for_each_entry(curr_item,&cscfg_mgr->data.csdev_desc_list,item){+if(curr_item->match_info.match_flags&feat_desc->match_flags){+err=cscfg_load_feat_csdev(curr_item->csdev,feat_desc,&curr_item->ops);+if(err)+returnerr;+}+}+return0;+}+/* check feature list for a named feature - call with mutex locked. */staticboolcscfg_match_list_feat(constchar*name){
@@ -53,6 +259,13 @@ static int cscfg_check_feat_for_cfg(struct cscfg_config_desc *cfg_desc)*/staticintcscfg_load_feat(structcscfg_feature_desc*feat_desc){+interr;++/* add feature to any matching registered devices */+err=cscfg_add_feat_to_csdevs(feat_desc);+if(err)+returnerr;+list_add(&feat_desc->item,&cscfg_mgr->data.feat_desc_list);return0;
@@ -71,6 +284,11 @@ static int cscfg_load_config(struct cscfg_config_desc *cfg_desc)if(err)returnerr;+/* add config to any matching registered device */+err=cscfg_add_cfg_to_csdevs(cfg_desc);+if(err)+returnerr;+list_add(&cfg_desc->item,&cscfg_mgr->data.config_desc_list);return0;
@@ -122,6 +340,136 @@ int cscfg_load_config_sets(struct cscfg_config_desc **cfg_descs,}EXPORT_SYMBOL_GPL(cscfg_load_config_sets);+/* Handle coresight device registration and add configs and features to devices */++/* iterate through config lists and load matching configs to device */+staticintcscfg_add_cfgs_csdev(structcoresight_device*csdev,+structcscfg_match_desc*info)+{+structcscfg_config_desc*curr_item;+interr=0;++list_for_each_entry(curr_item,&cscfg_mgr->data.config_desc_list,item){+err=cscfg_add_csdev_cfg(csdev,info,curr_item);+if(err)+break;+}+returnerr;+}++/* iterate through feature lists and load matching features to device */+staticintcscfg_add_feats_csdev(structcoresight_device*csdev,+structcscfg_match_desc*info,+structcscfg_csdev_feat_ops*ops)+{+structcscfg_feature_desc*curr_item;+interr=0;++if(!ops->load_feat)+return-EINVAL;++list_for_each_entry(curr_item,&cscfg_mgr->data.feat_desc_list,item){+if(curr_item->match_flags&info->match_flags){+err=cscfg_load_feat_csdev(csdev,curr_item,ops);+if(err)+break;+}+}+returnerr;+}++/* Add coresight device to list and copy its matching info */+staticintcscfg_list_add_csdev(structcoresight_device*csdev,+structcscfg_match_desc*info,+structcscfg_csdev_feat_ops*ops)+{+structcscfg_csdev_register*list_entry;++/* allocate the list entry structure */+list_entry=kzalloc(sizeof(structcscfg_csdev_register),GFP_KERNEL);+if(!list_entry)+return-ENOMEM;++list_entry->csdev=csdev;+list_entry->match_info.match_flags=info->match_flags;+list_entry->ops.load_feat=ops->load_feat;+list_add(&list_entry->item,&cscfg_mgr->data.csdev_desc_list);++INIT_LIST_HEAD(&csdev->feature_csdev_list);+INIT_LIST_HEAD(&csdev->config_csdev_list);+cscfg_mgr->data.nr_csdev++;++return0;+}++/* remove a coresight device from the list and free data */+staticvoidcscfg_list_remove_csdev(structcoresight_device*csdev)+{+structcscfg_csdev_register*curr_item,*tmp;++list_for_each_entry_safe(curr_item,tmp,&cscfg_mgr->data.csdev_desc_list,item){+if(curr_item->csdev==csdev){+list_del(&curr_item->item);+kfree(curr_item);+cscfg_mgr->data.nr_csdev--;+break;+}+}+}++/* register a coresight device with the syscfg api */+intcscfg_register_csdev(structcoresight_device*csdev,+structcscfg_match_desc*info,+structcscfg_csdev_feat_ops*ops)+{+intret=0;++mutex_lock(&cscfg_mutex);++/* add device to list of registered devices */+ret=cscfg_list_add_csdev(csdev,info,ops);+if(ret)+gotoreg_csdev_unlock;++/* now load any registered features and configs matching the device. */+ret=cscfg_add_feats_csdev(csdev,info,ops);+if(ret){+cscfg_list_remove_csdev(csdev);+gotoreg_csdev_unlock;+}++ret=cscfg_add_cfgs_csdev(csdev,info);+if(ret){+cscfg_list_remove_csdev(csdev);+gotoreg_csdev_unlock;+}++pr_info("CSCFG registered %s",dev_name(&csdev->dev));++reg_csdev_unlock:+mutex_unlock(&cscfg_mutex);+returnret;+}+EXPORT_SYMBOL_GPL(cscfg_register_csdev);++/* remove coresight device and update counts - syscfg device at 0 */+voidcscfg_unregister_csdev(structcoresight_device*csdev)+{+structcscfg_csdev_register*curr_item,*tmp;++mutex_lock(&cscfg_mutex);+list_for_each_entry_safe(curr_item,tmp,&cscfg_mgr->data.csdev_desc_list,item){+if(curr_item->csdev==csdev){+list_del(&curr_item->item);+kfree(curr_item);+cscfg_mgr->data.nr_csdev--;+break;+}+}+mutex_unlock(&cscfg_mutex);+}+EXPORT_SYMBOL_GPL(cscfg_unregister_csdev);+/* Initialise system configuration management device. */structdevice*to_device_cscfg(void)
@@ -240,6 +242,9 @@ struct coresight_device {intnr_links;boolhas_conns_grp;boolect_enabled;/* true only if associated ect device is enabled */+/* system configuration and feature lists */+structlist_headfeature_csdev_list;+structlist_headconfig_csdev_list;};/*
--
2.17.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
+/**
+ * List entry for Coresight devices that are registered as supporting complex
+ * config operations.
+ *
+ * @csdev: The registered device.
+ * @match_info: The matching type information.
+ * @ops: Operations supported by the registered device.
+ * @item: list entry.
+ */
+struct cscfg_csdev_register {
+ struct coresight_device *csdev;
+ struct cscfg_match_desc match_info;
+ struct cscfg_csdev_feat_ops ops;
+ struct list_head item;
+};
I would call this structure cscfg_registered_csdev and move it to
coresight-config.h. That way it is consistent with cscfg_config_csdev and
cscfg_feature_csdev and located all in the same file.
I may have to come back to this patch but for now it holds together.
More comments to come on Monday.
Thanks,
Mathieu
quoted hunk
+
/* internal core operations for cscfg */
int __init cscfg_init(void);
void __exit cscfg_exit(void);
@@ -240,6 +242,9 @@ struct coresight_device {intnr_links;boolhas_conns_grp;boolect_enabled;/* true only if associated ect device is enabled */+/* system configuration and feature lists */+structlist_headfeature_csdev_list;+structlist_headconfig_csdev_list;};/*
From: Mike Leach <hidden> Date: 2021-02-26 19:15:53
Hi Mathieu,
On Fri, 19 Feb 2021 at 18:43, Mathieu Poirier
[off-list ref] wrote:
[...]
quoted
+/**
+ * List entry for Coresight devices that are registered as supporting complex
+ * config operations.
+ *
+ * @csdev: The registered device.
+ * @match_info: The matching type information.
+ * @ops: Operations supported by the registered device.
+ * @item: list entry.
+ */
+struct cscfg_csdev_register {
+ struct coresight_device *csdev;
+ struct cscfg_match_desc match_info;
+ struct cscfg_csdev_feat_ops ops;
+ struct list_head item;
+};
I would call this structure cscfg_registered_csdev and move it to
coresight-config.h. That way it is consistent with cscfg_config_csdev and
cscfg_feature_csdev and located all in the same file.
I was trying to separate structures that are used to define
configurations and features, with those that are used to manage the
same. Hence, most things in coresight_config.h define configurations,
or their device loaded instance equivalents, and things in
coresight_syscfg.h are management items. I am happy to change the name
but would prefer is stay in coresight_syscfg.h
Thanks
Mike
I may have to come back to this patch but for now it holds together.
More comments to come on Monday.
Thanks,
Mathieu
quoted
+
/* internal core operations for cscfg */
int __init cscfg_init(void);
void __exit cscfg_exit(void);
@@ -240,6 +242,9 @@ struct coresight_device {intnr_links;boolhas_conns_grp;boolect_enabled;/* true only if associated ect device is enabled */+/* system configuration and feature lists */+structlist_headfeature_csdev_list;+structlist_headconfig_csdev_list;};/*--
2.17.1
--
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
On Fri, Feb 26, 2021 at 07:14:32PM +0000, Mike Leach wrote:
Hi Mathieu,
On Fri, 19 Feb 2021 at 18:43, Mathieu Poirier
[off-list ref] wrote:
quoted
[...]
quoted
+/**
+ * List entry for Coresight devices that are registered as supporting complex
+ * config operations.
+ *
+ * @csdev: The registered device.
+ * @match_info: The matching type information.
+ * @ops: Operations supported by the registered device.
+ * @item: list entry.
+ */
+struct cscfg_csdev_register {
+ struct coresight_device *csdev;
+ struct cscfg_match_desc match_info;
+ struct cscfg_csdev_feat_ops ops;
+ struct list_head item;
+};
I would call this structure cscfg_registered_csdev and move it to
coresight-config.h. That way it is consistent with cscfg_config_csdev and
cscfg_feature_csdev and located all in the same file.
I was trying to separate structures that are used to define
configurations and features, with those that are used to manage the
same. Hence, most things in coresight_config.h define configurations,
or their device loaded instance equivalents, and things in
coresight_syscfg.h are management items. I am happy to change the name
but would prefer is stay in coresight_syscfg.h
Hi Mike,
On Thu, Jan 28, 2021 at 05:09:28PM +0000, Mike Leach wrote:
quoted hunk
API for individual devices to register with the syscfg management
system is added.
Devices register with matching information, and any features or
configurations that match will be loaded into the device.
The feature and configuration loading is extended so that on load these
are loaded into any currently registered devices. This allows
configuration loading after devices have been registered.
Signed-off-by: Mike Leach <redacted>
---
.../hwtracing/coresight/coresight-config.h | 98 +++++
.../hwtracing/coresight/coresight-syscfg.c | 348 ++++++++++++++++++
.../hwtracing/coresight/coresight-syscfg.h | 20 +
include/linux/coresight.h | 5 +
4 files changed, 471 insertions(+)
Please rename this cscfg_regval_csdev to highlight the 1:1 mapping with
cscfg_regval_desc. Or rename cscfg_regval_desc to cscfg_reg_desc. I have no
opinion on which one it should be, as long as they are consistent. Doing so
really helps getting over the naming convention so that we can focus on the core
of the feature.
quoted hunk
+ struct cscfg_regval_desc value;
+ void *drv_store;
+};
+
+/**
+ * config parameter instance - part of a loaded feature.
+ *
+ * @feat: parent feature
+ * @reg: register value updated by this parameter.
+ * @current_value: current value of parameter - may be set by user via
+ * sysfs, or modified during device operation.
+ * @val64: true if 64 bit value
+ */
+struct cscfg_parameter_csdev {
+ struct cscfg_feature_csdev *feat;
+ struct cscfg_reg_csdev *reg;
+ u64 current_value;
+ bool val64;
+};
+
+/**
+ * Feature instance loaded into a CoreSight device.
+ *
+ * When a feature is loaded into a specific device, then this structure holds
+ * the connections between the register / parameter values used and the
+ * internal data structures that are written when the feature is enabled.
+ *
+ * Since applying a feature modifies internal data structures in the device,
+ * then we have a reference to the device spinlock to protect access to these
+ * structures (@csdev_spinlock).
+ *
+ * @desc: pointer to the static descriptor for this feature.
+ * @csdev: parent CoreSight device instance.
+ * @node: list entry into feature list for this device.
+ * @csdev_spinlock: device spinlock from csdev instance..
+ * @nr_params: number of parameters.
+ * @params: current parameter values on this device
+ * @nr_regs: number of registers to be programmed.
+ * @regs: Programming details for the registers
+ */
+struct cscfg_feature_csdev {
+ const struct cscfg_feature_desc *desc;
+ struct coresight_device *csdev;
+ struct list_head node;
+ spinlock_t *csdev_spinlock;
+ int nr_params;
+ struct cscfg_parameter_csdev *params;
+ int nr_regs;
+ struct cscfg_reg_csdev *regs;
+};
+
+/**
+ * Configuration instance when loaded into a CoreSight device.
+ *
+ * The instance contains references to loaded features on this device that are
+ * used by the configuration.
+ *
+ * @desc: reference to the descriptor for this configuration
+ * @csdev: parent coresight device for this configuration instance.
+ * @node: list entry within the coresight device
+ * @nr_feat: Number of features on this device that are used in the
+ * configuration.
+ * @feats: reference to the device features to enable.
+ * @enabled: true if configuration is enabled on this device.
+ */
+struct cscfg_config_csdev {
+ const struct cscfg_config_desc *desc;
+ struct coresight_device *csdev;
+ struct list_head node;
+ int nr_feat;
+ struct cscfg_feature_csdev **feats;
+ bool enabled;
+};
+
+/**
+ * Coresight device operations.
+ *
+ * Registered coresight devices provide these operations to manage feature
+ * instances compatible with the device hardware and drivers
+ *
+ * @load_feat: Pass a feature descriptor into the device and create the
+ * loaded feature instance (struct cscfg_feature_csdev).
+ */
+struct cscfg_csdev_feat_ops {
+ int (*load_feat)(struct coresight_device *csdev,
+ struct cscfg_feature_csdev *feat);
+};
+
#endif /* _CORESIGHT_CORESIGHT_CONFIG_H */
@@ -25,6 +25,212 @@ static struct cscfg_manager *cscfg_mgr;/* load features and configuations into the lists */+/* protect the cfg lists in the csdev instances */+staticDEFINE_MUTEX(cscfg_csdev_mutex);++/* get name feature instance from a coresight device list of features */+staticstructcscfg_feature_csdev*+cscfg_get_feat_csdev(structcoresight_device*csdev,constchar*name)+{+structcscfg_feature_csdev*feat=NULL;++list_for_each_entry(feat,&csdev->feature_csdev_list,node){+if(strcmp(feat->desc->name,name)==0)+returnfeat;+}+returnNULL;+}++/* allocate the device config instance - with max number of used features */+staticstructcscfg_config_csdev*+cscfg_alloc_csdev_cfg(structcoresight_device*csdev,intnr_feats)+{+structcscfg_config_csdev*dev_cfg=NULL;+structdevice*dev=csdev->dev.parent;++/* this is being allocated using the devm for the coresight device */+dev_cfg=devm_kzalloc(dev,sizeof(structcscfg_config_csdev),GFP_KERNEL);+if(!dev_cfg)+returnNULL;++dev_cfg->csdev=csdev;+dev_cfg->feats=devm_kcalloc(dev,nr_feats,+sizeof(structcscfg_feature_csdev*),+GFP_KERNEL);+if(!dev_cfg->feats)+dev_cfg=NULL;+returndev_cfg;+}++/* check match info between used feature from the config and a regisered device */+staticboolcscfg_match_feat_info(structcscfg_match_desc*used_cmp,+structcscfg_match_desc*reg_dev)+{+/* if flags don't match then fail early */+if(!(used_cmp->match_flags®_dev->match_flags))+returnfalse;++returntrue;+}++/* Load a config into a device if there are feature matches between config and device */+staticintcscfg_add_csdev_cfg(structcoresight_device*csdev,+structcscfg_match_desc*match_info,+structcscfg_config_desc*cfg_desc)
struct cscfg_feature_csdev *feat_csdev;
Please appy this kind of naming convention throughout the patchset.
+ int checked;
+
+ /* look at each required feature and see if it matches any feature on the device */
+ for (checked = 0; checked < cfg_desc->nr_refs; checked++) {
+ feat_ref = &cfg_desc->refs[checked];
+ if (cscfg_match_feat_info(&feat_ref->match, match_info)) {
+ /* device matched - get the feature */
+ feat = cscfg_get_feat_csdev(csdev, feat_ref->name);
+ if (!feat)
+ return -EINVAL;
+ if (!dev_cfg) {
+ dev_cfg = cscfg_alloc_csdev_cfg(csdev, cfg_desc->nr_refs);
+ if (!dev_cfg)
+ return -ENOMEM;
+ dev_cfg->desc = cfg_desc;
+ }
+ dev_cfg->feats[dev_cfg->nr_feat++] = feat;
+ }
+ }
+ /* if matched features, add config to device.*/
+ if (dev_cfg) {
+ mutex_lock(&cscfg_csdev_mutex);
+ list_add(&dev_cfg->node, &csdev->config_csdev_list);
+ mutex_unlock(&cscfg_csdev_mutex);
+ }
+
+ return 0;
+}
+
+/*
+ * Add the config to the set of registered devices - call with mutex locked.
+ * Iterates through devices - any device that matches one or more of the
+ * configuration features will load it, the others will ignore it.
+ */
+static int cscfg_add_cfg_to_csdevs(struct cscfg_config_desc *cfg_desc)
+{
+ struct cscfg_csdev_register *curr_item;
+ int err;
+
+ list_for_each_entry(curr_item, &cscfg_mgr->data.csdev_desc_list, item) {
+ err = cscfg_add_csdev_cfg(curr_item->csdev, &curr_item->match_info, cfg_desc);
+ if (err)
+ return err;
+ }
+ return 0;
+}
+
+/*
+ * Allocate a feature object for load into a csdev.
+ * memory allocated using the csdev->dev object using devm managed allocator.
+ */
+static struct cscfg_feature_csdev *
+cscfg_alloc_csdev_feat(struct coresight_device *csdev, struct cscfg_feature_desc *feat_desc)
+{
+ struct cscfg_feature_csdev *feat = NULL;
struct cscfg_feature_csdev *feat_csdev = NULL;
quoted hunk
+ struct device *dev = csdev->dev.parent;
+ int i;
+
+ feat = devm_kzalloc(dev, sizeof(struct cscfg_feature_csdev), GFP_KERNEL);
+ if (!feat)
+ return NULL;
+
+ /* parameters are optional - could be 0 */
+ feat->nr_params = feat_desc->nr_params;
+
+ /*
+ * if we need parameters, zero alloc the space here, the load routine in
+ * the csdev device driver will fill out some information according to
+ * feature descriptor.
+ */
+ if (feat->nr_params) {
+ feat->params = devm_kcalloc(dev, feat->nr_params,
+ sizeof(struct cscfg_parameter_csdev),
+ GFP_KERNEL);
+ if (!feat->params)
+ return NULL;
+
+ /*
+ * fill in the feature reference in the param - other fields
+ * handled by loader in csdev.
+ */
+ for (i = 0; i < feat->nr_params; i++)
+ feat->params[i].feat = feat;
+ }
+
+ /*
+ * Always have registers to program - again the load routine in csdev device
+ * will fill out according to feature descriptor and device requirements.
+ */
+ feat->nr_regs = feat_desc->nr_regs;
+ feat->regs = devm_kcalloc(dev, feat->nr_regs,
+ sizeof(struct cscfg_reg_csdev), GFP_KERNEL);
+ if (!feat->regs)
+ return NULL;
+
+ /* load the feature default values */
+ feat->desc = feat_desc;
+ feat->csdev = csdev;
+
+ return feat;
+}
+
+/* load one feature into one coresight device */
+static int cscfg_load_feat_csdev(struct coresight_device *csdev,
+ struct cscfg_feature_desc *feat_desc,
+ struct cscfg_csdev_feat_ops *ops)
+{
+ struct cscfg_feature_csdev *feat_csdev;
+ int err;
+
+ if (!ops->load_feat)
+ return -EINVAL;
+
+ feat_csdev = cscfg_alloc_csdev_feat(csdev, feat_desc);
+ if (!feat_csdev)
+ return -ENOMEM;
+
+ /* load the feature into the device - may modify default ops*/
+ err = ops->load_feat(csdev, feat_csdev);
+ if (err)
+ return err;
+
+ /* add to internal csdev feature list */
+ mutex_lock(&cscfg_csdev_mutex);
+ list_add(&feat_csdev->node, &csdev->feature_csdev_list);
+ mutex_unlock(&cscfg_csdev_mutex);
+
+ return 0;
+}
+
+/*
+ * Add feature to any matching devices - call with mutex locked.
+ * Iterates through devices - any device that matches the feature will be
+ * called to load it.
+ */
+static int cscfg_add_feat_to_csdevs(struct cscfg_feature_desc *feat_desc)
+{
+ struct cscfg_csdev_register *curr_item;
+ int err;
+
+ list_for_each_entry(curr_item, &cscfg_mgr->data.csdev_desc_list, item) {
+ if (curr_item->match_info.match_flags & feat_desc->match_flags) {
+ err = cscfg_load_feat_csdev(curr_item->csdev, feat_desc, &curr_item->ops);
+ if (err)
+ return err;
+ }
+ }
+ return 0;
+}
+
/* check feature list for a named feature - call with mutex locked. */
static bool cscfg_match_list_feat(const char *name)
{
@@ -53,6 +259,13 @@ static int cscfg_check_feat_for_cfg(struct cscfg_config_desc *cfg_desc) */ static int cscfg_load_feat(struct cscfg_feature_desc *feat_desc) {+ int err;++ /* add feature to any matching registered devices */+ err = cscfg_add_feat_to_csdevs(feat_desc);+ if (err)+ return err;+ list_add(&feat_desc->item, &cscfg_mgr->data.feat_desc_list); return 0;
@@ -71,6 +284,11 @@ static int cscfg_load_config(struct cscfg_config_desc *cfg_desc) if (err) return err;+ /* add config to any matching registered device */+ err = cscfg_add_cfg_to_csdevs(cfg_desc);+ if (err)+ return err;+ list_add(&cfg_desc->item, &cscfg_mgr->data.config_desc_list); return 0;
@@ -122,6 +340,136 @@ int cscfg_load_config_sets(struct cscfg_config_desc **cfg_descs, } EXPORT_SYMBOL_GPL(cscfg_load_config_sets);+/* Handle coresight device registration and add configs and features to devices */++/* iterate through config lists and load matching configs to device */+static int cscfg_add_cfgs_csdev(struct coresight_device *csdev,+ struct cscfg_match_desc *info)+{+ struct cscfg_config_desc *curr_item;+ int err = 0;++ list_for_each_entry(curr_item, &cscfg_mgr->data.config_desc_list, item) {+ err = cscfg_add_csdev_cfg(csdev, info, curr_item);+ if (err)+ break;+ }+ return err;+}++/* iterate through feature lists and load matching features to device */+static int cscfg_add_feats_csdev(struct coresight_device *csdev,+ struct cscfg_match_desc *info,+ struct cscfg_csdev_feat_ops *ops)+{+ struct cscfg_feature_desc *curr_item;+ int err = 0;++ if (!ops->load_feat)+ return -EINVAL;++ list_for_each_entry(curr_item, &cscfg_mgr->data.feat_desc_list, item) {+ if (curr_item->match_flags & info->match_flags) {+ err = cscfg_load_feat_csdev(csdev, curr_item, ops);+ if (err)+ break;+ }+ }+ return err;+}++/* Add coresight device to list and copy its matching info */+static int cscfg_list_add_csdev(struct coresight_device *csdev,+ struct cscfg_match_desc *info,+ struct cscfg_csdev_feat_ops *ops)+{+ struct cscfg_csdev_register *list_entry;++ /* allocate the list entry structure */+ list_entry = kzalloc(sizeof(struct cscfg_csdev_register), GFP_KERNEL);+ if (!list_entry)+ return -ENOMEM;++ list_entry->csdev = csdev;+ list_entry->match_info.match_flags = info->match_flags;+ list_entry->ops.load_feat = ops->load_feat;+ list_add(&list_entry->item, &cscfg_mgr->data.csdev_desc_list);++ INIT_LIST_HEAD(&csdev->feature_csdev_list);+ INIT_LIST_HEAD(&csdev->config_csdev_list);+ cscfg_mgr->data.nr_csdev++;++ return 0;+}++/* remove a coresight device from the list and free data */+static void cscfg_list_remove_csdev(struct coresight_device *csdev)+{+ struct cscfg_csdev_register *curr_item, *tmp;++ list_for_each_entry_safe(curr_item, tmp, &cscfg_mgr->data.csdev_desc_list, item) {+ if (curr_item->csdev == csdev) {+ list_del(&curr_item->item);+ kfree(curr_item);+ cscfg_mgr->data.nr_csdev--;+ break;+ }+ }+}++/* register a coresight device with the syscfg api */+int cscfg_register_csdev(struct coresight_device *csdev,+ struct cscfg_match_desc *info,+ struct cscfg_csdev_feat_ops *ops)+{+ int ret = 0;++ mutex_lock(&cscfg_mutex);++ /* add device to list of registered devices */+ ret = cscfg_list_add_csdev(csdev, info, ops);+ if (ret)+ goto reg_csdev_unlock;++ /* now load any registered features and configs matching the device. */+ ret = cscfg_add_feats_csdev(csdev, info, ops);+ if (ret) {+ cscfg_list_remove_csdev(csdev);+ goto reg_csdev_unlock;+ }++ ret = cscfg_add_cfgs_csdev(csdev, info);+ if (ret) {+ cscfg_list_remove_csdev(csdev);+ goto reg_csdev_unlock;+ }++ pr_info("CSCFG registered %s", dev_name(&csdev->dev));++reg_csdev_unlock:+ mutex_unlock(&cscfg_mutex);+ return ret;+}+EXPORT_SYMBOL_GPL(cscfg_register_csdev);++/* remove coresight device and update counts - syscfg device at 0 */+void cscfg_unregister_csdev(struct coresight_device *csdev)+{+ struct cscfg_csdev_register *curr_item, *tmp;++ mutex_lock(&cscfg_mutex);+ list_for_each_entry_safe(curr_item, tmp, &cscfg_mgr->data.csdev_desc_list, item) {+ if (curr_item->csdev == csdev) {+ list_del(&curr_item->item);+ kfree(curr_item);+ cscfg_mgr->data.nr_csdev--;+ break;+ }+ }+ mutex_unlock(&cscfg_mutex);+}+EXPORT_SYMBOL_GPL(cscfg_unregister_csdev);+ /* Initialise system configuration management device. */ struct device *to_device_cscfg(void)
@@ -240,6 +242,9 @@ struct coresight_device {intnr_links;boolhas_conns_grp;boolect_enabled;/* true only if associated ect device is enabled */+/* system configuration and feature lists */+structlist_headfeature_csdev_list;+structlist_headconfig_csdev_list;};/*
From: Mike Leach <hidden> Date: 2021-02-26 19:17:48
Hi Mathieu,
On Mon, 22 Feb 2021 at 17:38, Mathieu Poirier
[off-list ref] wrote:
Hi Mike,
On Thu, Jan 28, 2021 at 05:09:28PM +0000, Mike Leach wrote:
quoted
API for individual devices to register with the syscfg management
system is added.
Devices register with matching information, and any features or
configurations that match will be loaded into the device.
The feature and configuration loading is extended so that on load these
are loaded into any currently registered devices. This allows
configuration loading after devices have been registered.
Signed-off-by: Mike Leach <redacted>
---
.../hwtracing/coresight/coresight-config.h | 98 +++++
.../hwtracing/coresight/coresight-syscfg.c | 348 ++++++++++++++++++
.../hwtracing/coresight/coresight-syscfg.h | 20 +
include/linux/coresight.h | 5 +
4 files changed, 471 insertions(+)
Please rename this cscfg_regval_csdev to highlight the 1:1 mapping with
cscfg_regval_desc. Or rename cscfg_regval_desc to cscfg_reg_desc. I have no
opinion on which one it should be, as long as they are consistent. Doing so
really helps getting over the naming convention so that we can focus on the core
of the feature.
Will do.
quoted
+ struct cscfg_regval_desc value;
+ void *drv_store;
+};
+
+/**
+ * config parameter instance - part of a loaded feature.
+ *
+ * @feat: parent feature
+ * @reg: register value updated by this parameter.
+ * @current_value: current value of parameter - may be set by user via
+ * sysfs, or modified during device operation.
+ * @val64: true if 64 bit value
+ */
+struct cscfg_parameter_csdev {
+ struct cscfg_feature_csdev *feat;
+ struct cscfg_reg_csdev *reg;
+ u64 current_value;
+ bool val64;
+};
+
+/**
+ * Feature instance loaded into a CoreSight device.
+ *
+ * When a feature is loaded into a specific device, then this structure holds
+ * the connections between the register / parameter values used and the
+ * internal data structures that are written when the feature is enabled.
+ *
+ * Since applying a feature modifies internal data structures in the device,
+ * then we have a reference to the device spinlock to protect access to these
+ * structures (@csdev_spinlock).
+ *
+ * @desc: pointer to the static descriptor for this feature.
+ * @csdev: parent CoreSight device instance.
+ * @node: list entry into feature list for this device.
+ * @csdev_spinlock: device spinlock from csdev instance..
+ * @nr_params: number of parameters.
+ * @params: current parameter values on this device
+ * @nr_regs: number of registers to be programmed.
+ * @regs: Programming details for the registers
+ */
+struct cscfg_feature_csdev {
+ const struct cscfg_feature_desc *desc;
+ struct coresight_device *csdev;
+ struct list_head node;
+ spinlock_t *csdev_spinlock;
+ int nr_params;
+ struct cscfg_parameter_csdev *params;
+ int nr_regs;
+ struct cscfg_reg_csdev *regs;
+};
+
+/**
+ * Configuration instance when loaded into a CoreSight device.
+ *
+ * The instance contains references to loaded features on this device that are
+ * used by the configuration.
+ *
+ * @desc: reference to the descriptor for this configuration
+ * @csdev: parent coresight device for this configuration instance.
+ * @node: list entry within the coresight device
+ * @nr_feat: Number of features on this device that are used in the
+ * configuration.
+ * @feats: reference to the device features to enable.
+ * @enabled: true if configuration is enabled on this device.
+ */
+struct cscfg_config_csdev {
+ const struct cscfg_config_desc *desc;
+ struct coresight_device *csdev;
+ struct list_head node;
+ int nr_feat;
+ struct cscfg_feature_csdev **feats;
+ bool enabled;
+};
+
+/**
+ * Coresight device operations.
+ *
+ * Registered coresight devices provide these operations to manage feature
+ * instances compatible with the device hardware and drivers
+ *
+ * @load_feat: Pass a feature descriptor into the device and create the
+ * loaded feature instance (struct cscfg_feature_csdev).
+ */
+struct cscfg_csdev_feat_ops {
+ int (*load_feat)(struct coresight_device *csdev,
+ struct cscfg_feature_csdev *feat);
+};
+
#endif /* _CORESIGHT_CORESIGHT_CONFIG_H */
@@ -25,6 +25,212 @@ static struct cscfg_manager *cscfg_mgr;/* load features and configuations into the lists */+/* protect the cfg lists in the csdev instances */+staticDEFINE_MUTEX(cscfg_csdev_mutex);++/* get name feature instance from a coresight device list of features */+staticstructcscfg_feature_csdev*+cscfg_get_feat_csdev(structcoresight_device*csdev,constchar*name)+{+structcscfg_feature_csdev*feat=NULL;++list_for_each_entry(feat,&csdev->feature_csdev_list,node){+if(strcmp(feat->desc->name,name)==0)+returnfeat;+}+returnNULL;+}++/* allocate the device config instance - with max number of used features */+staticstructcscfg_config_csdev*+cscfg_alloc_csdev_cfg(structcoresight_device*csdev,intnr_feats)+{+structcscfg_config_csdev*dev_cfg=NULL;+structdevice*dev=csdev->dev.parent;++/* this is being allocated using the devm for the coresight device */+dev_cfg=devm_kzalloc(dev,sizeof(structcscfg_config_csdev),GFP_KERNEL);+if(!dev_cfg)+returnNULL;++dev_cfg->csdev=csdev;+dev_cfg->feats=devm_kcalloc(dev,nr_feats,+sizeof(structcscfg_feature_csdev*),+GFP_KERNEL);+if(!dev_cfg->feats)+dev_cfg=NULL;+returndev_cfg;+}++/* check match info between used feature from the config and a regisered device */+staticboolcscfg_match_feat_info(structcscfg_match_desc*used_cmp,+structcscfg_match_desc*reg_dev)+{+/* if flags don't match then fail early */+if(!(used_cmp->match_flags®_dev->match_flags))+returnfalse;++returntrue;+}++/* Load a config into a device if there are feature matches between config and device */+staticintcscfg_add_csdev_cfg(structcoresight_device*csdev,+structcscfg_match_desc*match_info,+structcscfg_config_desc*cfg_desc)
Please appy this kind of naming convention throughout the patchset.
Agreed - I'll update the
nameing convention in the next set.
Thanks
Mike
quoted
+ int checked;
+
+ /* look at each required feature and see if it matches any feature on the device */
+ for (checked = 0; checked < cfg_desc->nr_refs; checked++) {
+ feat_ref = &cfg_desc->refs[checked];
+ if (cscfg_match_feat_info(&feat_ref->match, match_info)) {
+ /* device matched - get the feature */
+ feat = cscfg_get_feat_csdev(csdev, feat_ref->name);
+ if (!feat)
+ return -EINVAL;
+ if (!dev_cfg) {
+ dev_cfg = cscfg_alloc_csdev_cfg(csdev, cfg_desc->nr_refs);
+ if (!dev_cfg)
+ return -ENOMEM;
+ dev_cfg->desc = cfg_desc;
+ }
+ dev_cfg->feats[dev_cfg->nr_feat++] = feat;
+ }
+ }
+ /* if matched features, add config to device.*/
+ if (dev_cfg) {
+ mutex_lock(&cscfg_csdev_mutex);
+ list_add(&dev_cfg->node, &csdev->config_csdev_list);
+ mutex_unlock(&cscfg_csdev_mutex);
+ }
+
+ return 0;
+}
+
+/*
+ * Add the config to the set of registered devices - call with mutex locked.
+ * Iterates through devices - any device that matches one or more of the
+ * configuration features will load it, the others will ignore it.
+ */
+static int cscfg_add_cfg_to_csdevs(struct cscfg_config_desc *cfg_desc)
+{
+ struct cscfg_csdev_register *curr_item;
+ int err;
+
+ list_for_each_entry(curr_item, &cscfg_mgr->data.csdev_desc_list, item) {
+ err = cscfg_add_csdev_cfg(curr_item->csdev, &curr_item->match_info, cfg_desc);
+ if (err)
+ return err;
+ }
+ return 0;
+}
+
+/*
+ * Allocate a feature object for load into a csdev.
+ * memory allocated using the csdev->dev object using devm managed allocator.
+ */
+static struct cscfg_feature_csdev *
+cscfg_alloc_csdev_feat(struct coresight_device *csdev, struct cscfg_feature_desc *feat_desc)
+{
+ struct cscfg_feature_csdev *feat = NULL;
struct cscfg_feature_csdev *feat_csdev = NULL;
quoted
+ struct device *dev = csdev->dev.parent;
+ int i;
+
+ feat = devm_kzalloc(dev, sizeof(struct cscfg_feature_csdev), GFP_KERNEL);
+ if (!feat)
+ return NULL;
+
+ /* parameters are optional - could be 0 */
+ feat->nr_params = feat_desc->nr_params;
+
+ /*
+ * if we need parameters, zero alloc the space here, the load routine in
+ * the csdev device driver will fill out some information according to
+ * feature descriptor.
+ */
+ if (feat->nr_params) {
+ feat->params = devm_kcalloc(dev, feat->nr_params,
+ sizeof(struct cscfg_parameter_csdev),
+ GFP_KERNEL);
+ if (!feat->params)
+ return NULL;
+
+ /*
+ * fill in the feature reference in the param - other fields
+ * handled by loader in csdev.
+ */
+ for (i = 0; i < feat->nr_params; i++)
+ feat->params[i].feat = feat;
+ }
+
+ /*
+ * Always have registers to program - again the load routine in csdev device
+ * will fill out according to feature descriptor and device requirements.
+ */
+ feat->nr_regs = feat_desc->nr_regs;
+ feat->regs = devm_kcalloc(dev, feat->nr_regs,
+ sizeof(struct cscfg_reg_csdev), GFP_KERNEL);
+ if (!feat->regs)
+ return NULL;
+
+ /* load the feature default values */
+ feat->desc = feat_desc;
+ feat->csdev = csdev;
+
+ return feat;
+}
+
+/* load one feature into one coresight device */
+static int cscfg_load_feat_csdev(struct coresight_device *csdev,
+ struct cscfg_feature_desc *feat_desc,
+ struct cscfg_csdev_feat_ops *ops)
+{
+ struct cscfg_feature_csdev *feat_csdev;
+ int err;
+
+ if (!ops->load_feat)
+ return -EINVAL;
+
+ feat_csdev = cscfg_alloc_csdev_feat(csdev, feat_desc);
+ if (!feat_csdev)
+ return -ENOMEM;
+
+ /* load the feature into the device - may modify default ops*/
+ err = ops->load_feat(csdev, feat_csdev);
+ if (err)
+ return err;
+
+ /* add to internal csdev feature list */
+ mutex_lock(&cscfg_csdev_mutex);
+ list_add(&feat_csdev->node, &csdev->feature_csdev_list);
+ mutex_unlock(&cscfg_csdev_mutex);
+
+ return 0;
+}
+
+/*
+ * Add feature to any matching devices - call with mutex locked.
+ * Iterates through devices - any device that matches the feature will be
+ * called to load it.
+ */
+static int cscfg_add_feat_to_csdevs(struct cscfg_feature_desc *feat_desc)
+{
+ struct cscfg_csdev_register *curr_item;
+ int err;
+
+ list_for_each_entry(curr_item, &cscfg_mgr->data.csdev_desc_list, item) {
+ if (curr_item->match_info.match_flags & feat_desc->match_flags) {
+ err = cscfg_load_feat_csdev(curr_item->csdev, feat_desc, &curr_item->ops);
+ if (err)
+ return err;
+ }
+ }
+ return 0;
+}
+
/* check feature list for a named feature - call with mutex locked. */
static bool cscfg_match_list_feat(const char *name)
{
@@ -53,6 +259,13 @@ static int cscfg_check_feat_for_cfg(struct cscfg_config_desc *cfg_desc) */ static int cscfg_load_feat(struct cscfg_feature_desc *feat_desc) {+ int err;++ /* add feature to any matching registered devices */+ err = cscfg_add_feat_to_csdevs(feat_desc);+ if (err)+ return err;+ list_add(&feat_desc->item, &cscfg_mgr->data.feat_desc_list); return 0;
@@ -71,6 +284,11 @@ static int cscfg_load_config(struct cscfg_config_desc *cfg_desc) if (err) return err;+ /* add config to any matching registered device */+ err = cscfg_add_cfg_to_csdevs(cfg_desc);+ if (err)+ return err;+ list_add(&cfg_desc->item, &cscfg_mgr->data.config_desc_list); return 0;
@@ -122,6 +340,136 @@ int cscfg_load_config_sets(struct cscfg_config_desc **cfg_descs, } EXPORT_SYMBOL_GPL(cscfg_load_config_sets);+/* Handle coresight device registration and add configs and features to devices */++/* iterate through config lists and load matching configs to device */+static int cscfg_add_cfgs_csdev(struct coresight_device *csdev,+ struct cscfg_match_desc *info)+{+ struct cscfg_config_desc *curr_item;+ int err = 0;++ list_for_each_entry(curr_item, &cscfg_mgr->data.config_desc_list, item) {+ err = cscfg_add_csdev_cfg(csdev, info, curr_item);+ if (err)+ break;+ }+ return err;+}++/* iterate through feature lists and load matching features to device */+static int cscfg_add_feats_csdev(struct coresight_device *csdev,+ struct cscfg_match_desc *info,+ struct cscfg_csdev_feat_ops *ops)+{+ struct cscfg_feature_desc *curr_item;+ int err = 0;++ if (!ops->load_feat)+ return -EINVAL;++ list_for_each_entry(curr_item, &cscfg_mgr->data.feat_desc_list, item) {+ if (curr_item->match_flags & info->match_flags) {+ err = cscfg_load_feat_csdev(csdev, curr_item, ops);+ if (err)+ break;+ }+ }+ return err;+}++/* Add coresight device to list and copy its matching info */+static int cscfg_list_add_csdev(struct coresight_device *csdev,+ struct cscfg_match_desc *info,+ struct cscfg_csdev_feat_ops *ops)+{+ struct cscfg_csdev_register *list_entry;++ /* allocate the list entry structure */+ list_entry = kzalloc(sizeof(struct cscfg_csdev_register), GFP_KERNEL);+ if (!list_entry)+ return -ENOMEM;++ list_entry->csdev = csdev;+ list_entry->match_info.match_flags = info->match_flags;+ list_entry->ops.load_feat = ops->load_feat;+ list_add(&list_entry->item, &cscfg_mgr->data.csdev_desc_list);++ INIT_LIST_HEAD(&csdev->feature_csdev_list);+ INIT_LIST_HEAD(&csdev->config_csdev_list);+ cscfg_mgr->data.nr_csdev++;++ return 0;+}++/* remove a coresight device from the list and free data */+static void cscfg_list_remove_csdev(struct coresight_device *csdev)+{+ struct cscfg_csdev_register *curr_item, *tmp;++ list_for_each_entry_safe(curr_item, tmp, &cscfg_mgr->data.csdev_desc_list, item) {+ if (curr_item->csdev == csdev) {+ list_del(&curr_item->item);+ kfree(curr_item);+ cscfg_mgr->data.nr_csdev--;+ break;+ }+ }+}++/* register a coresight device with the syscfg api */+int cscfg_register_csdev(struct coresight_device *csdev,+ struct cscfg_match_desc *info,+ struct cscfg_csdev_feat_ops *ops)+{+ int ret = 0;++ mutex_lock(&cscfg_mutex);++ /* add device to list of registered devices */+ ret = cscfg_list_add_csdev(csdev, info, ops);+ if (ret)+ goto reg_csdev_unlock;++ /* now load any registered features and configs matching the device. */+ ret = cscfg_add_feats_csdev(csdev, info, ops);+ if (ret) {+ cscfg_list_remove_csdev(csdev);+ goto reg_csdev_unlock;+ }++ ret = cscfg_add_cfgs_csdev(csdev, info);+ if (ret) {+ cscfg_list_remove_csdev(csdev);+ goto reg_csdev_unlock;+ }++ pr_info("CSCFG registered %s", dev_name(&csdev->dev));++reg_csdev_unlock:+ mutex_unlock(&cscfg_mutex);+ return ret;+}+EXPORT_SYMBOL_GPL(cscfg_register_csdev);++/* remove coresight device and update counts - syscfg device at 0 */+void cscfg_unregister_csdev(struct coresight_device *csdev)+{+ struct cscfg_csdev_register *curr_item, *tmp;++ mutex_lock(&cscfg_mutex);+ list_for_each_entry_safe(curr_item, tmp, &cscfg_mgr->data.csdev_desc_list, item) {+ if (curr_item->csdev == csdev) {+ list_del(&curr_item->item);+ kfree(curr_item);+ cscfg_mgr->data.nr_csdev--;+ break;+ }+ }+ mutex_unlock(&cscfg_mutex);+}+EXPORT_SYMBOL_GPL(cscfg_unregister_csdev);+ /* Initialise system configuration management device. */ struct device *to_device_cscfg(void)
@@ -240,6 +242,9 @@ struct coresight_device {intnr_links;boolhas_conns_grp;boolect_enabled;/* true only if associated ect device is enabled */+/* system configuration and feature lists */+structlist_headfeature_csdev_list;+structlist_headconfig_csdev_list;};/*--
2.17.1
--
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel