From patchwork Fri Oct 30 17:56:47 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Leach X-Patchwork-Id: 11870457 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5BC57C55178 for ; Fri, 30 Oct 2020 17:59:09 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id A9E7A20724 for ; Fri, 30 Oct 2020 17:59:08 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="x8p932DX"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="dVTEbU+r" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org A9E7A20724 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:MIME-Version:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:References:In-Reply-To:Message-Id:Date:Subject:To: From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=0R5rLgxiHEyPRkRc0akzZnKgFDg65kcNSBWqjT2HnkI=; b=x8p932DX0UfbZQ6GnSxXIl8G7k 8397Gdss3MgJEI5LERQTVQU3m35A5NTJ5KGfYjFqO9NpPD2b1xGV1LooDgoO0guwoFkODnZoMdesH FksvYBdHPLSIoI+QJ4qwmr7D090FuH/RR+GBqYhzr2I6J5iSmGTdijblP3fs0TmQghCUzgk/QfR6X vbbq9si/Kh7vUvOLZOpX11Jgk0Q/kZ1vCE8hIYbVBMh6Nxsyb872+z6Khd+CyCkKBlQxog6GPVOOp e+Qsr8TKxrcuwYdcux6EMf37EqpLbraRM5qsb9YL9+PlrwSBRW6RmVyIsXTK8YPvk9Roy6bPN2mOq s0bN3OFA==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kYYeP-0003pt-Sl; Fri, 30 Oct 2020 17:57:21 +0000 Received: from mail-wr1-x430.google.com ([2a00:1450:4864:20::430]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kYYe6-0003kE-IJ for linux-arm-kernel@lists.infradead.org; Fri, 30 Oct 2020 17:57:10 +0000 Received: by mail-wr1-x430.google.com with SMTP id n15so7441211wrq.2 for ; Fri, 30 Oct 2020 10:57:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=oAiUyQ9hQl3HDYwMgFf883xMgfsH2J1MaaNjqhY+ygQ=; b=dVTEbU+rhsxFT/dSoRSAI7jM6cdfpOU/6bN6vLp23/LWozVWW4adLHRAirjTJRoy7k UKuF4VEY9kzZL4yli24Pa3fCTrHTi+gccNeQHrZVEtMrgug+8H86ylXLtX3V21cvtKsQ HLxkOKZUWr0RcA1x4dCBTM57kyQcTqHjfyeOCCPp2hRbPiYd3q1P7CXbMLeUEBaPFmCO oW0k4QjVQbpDjW5wxlfFgT05Jmv0lToXNnCtKeTab1QmsXOVpoXISNbdD4CbP/B7KLWV pjR9gYCPohrc7SPCGPJHkS877H8AXNxE8LZVvSkwNH0eyvL2V6er9WWX6KcTDgaWMBl/ yxIw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=oAiUyQ9hQl3HDYwMgFf883xMgfsH2J1MaaNjqhY+ygQ=; b=qMRHL4zuu8WdLrCdwKugPaDCr1SDiPIe9u7PjudCcs19oCN4fe56ipZRoBC9Ans2WG 3Y60aq1ybYsFQWitI8pfxiioGwnVy0ed7ivY3OEkYDbkf4L2nrFmd71/v3Vq7PNUEE+t JQv0F1eSKo7PxE0J19tBsiKwrJMry3NcF+kiZaPS2eKalgmNYjqpVLa6qVdujBMZDhGz GOEXTJ6ab6Oj+e8QKUvy5lmqd5dSQgYWF5XbpExw/ai+sfHlYRK9b7v6mlaE6+OV9f23 RbhNVQJ2DcYIPDYsYy7Si5Q6ihxTBh3CM0E52lPMIm3w19qieapV6VBac27s0y1qIhmZ gAjw== X-Gm-Message-State: AOAM533kIjYu06VjAXUvvhd0XArNc0bbzVYhsTWxIkuObzeJVui5whJo 71O5XgBx13V4efrtA2SX4f/kfg+B6j/vGQ== X-Google-Smtp-Source: ABdhPJx2mPq9jFRrAeCo0z3ZmN/jsjlrUiWZHq1Xysj/luAXEfw9OqHWdxUl9x63lfMciNJR1B31ZQ== X-Received: by 2002:a5d:4103:: with SMTP id l3mr4661626wrp.260.1604080619184; Fri, 30 Oct 2020 10:56:59 -0700 (PDT) Received: from linaro.org ([2a00:23c5:6801:1801:4964:83f8:d2e7:f2c9]) by smtp.gmail.com with ESMTPSA id o129sm5615563wmb.25.2020.10.30.10.56.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 30 Oct 2020 10:56:58 -0700 (PDT) From: Mike Leach To: linux-arm-kernel@lists.infradead.org, coresight@lists.linaro.org, mathieu.poirier@linaro.org Subject: [RFC PATCH v3 1/9] coresight: syscfg: Initial coresight system configuration Date: Fri, 30 Oct 2020 17:56:47 +0000 Message-Id: <20201030175655.30126-2-mike.leach@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201030175655.30126-1-mike.leach@linaro.org> References: <20201030175655.30126-1-mike.leach@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201030_135702_662160_768042DE X-CRM114-Status: GOOD ( 38.95 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: yabinc@google.com, Mike Leach , suzuki.poulose@arm.com MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org 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 --- drivers/hwtracing/coresight/Makefile | 2 +- .../hwtracing/coresight/coresight-config.h | 170 ++++++++++++ drivers/hwtracing/coresight/coresight-core.c | 12 +- .../hwtracing/coresight/coresight-etm-perf.c | 2 +- .../hwtracing/coresight/coresight-etm-perf.h | 2 +- .../hwtracing/coresight/coresight-syscfg.c | 247 ++++++++++++++++++ .../hwtracing/coresight/coresight-syscfg.h | 57 ++++ 7 files changed, 488 insertions(+), 4 deletions(-) create mode 100644 drivers/hwtracing/coresight/coresight-config.h create mode 100644 drivers/hwtracing/coresight/coresight-syscfg.c create mode 100644 drivers/hwtracing/coresight/coresight-syscfg.h diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile index f20e357758d1..4ce854c434b1 100644 --- a/drivers/hwtracing/coresight/Makefile +++ b/drivers/hwtracing/coresight/Makefile @@ -4,7 +4,7 @@ # obj-$(CONFIG_CORESIGHT) += coresight.o coresight-y := coresight-core.o coresight-etm-perf.o coresight-platform.o \ - coresight-sysfs.o + coresight-sysfs.o coresight-syscfg.o obj-$(CONFIG_CORESIGHT_LINK_AND_SINK_TMC) += coresight-tmc.o coresight-tmc-y := coresight-tmc-core.o coresight-tmc-etf.o \ coresight-tmc-etr.o diff --git a/drivers/hwtracing/coresight/coresight-config.h b/drivers/hwtracing/coresight/coresight-config.h new file mode 100644 index 000000000000..0d9ae1dc4517 --- /dev/null +++ b/drivers/hwtracing/coresight/coresight-config.h @@ -0,0 +1,170 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 Linaro Limited, All rights reserved. + * Author: Mike Leach + */ + +#ifndef _CORESIGHT_CORESIGHT_CONFIG_H +#define _CORESIGHT_CORESIGHT_CONFIG_H + +#include +#include + +/* CoreSight Configuration - complex component and system config handling */ + +/* generic register flags */ +#define CS_CFG_REG_STD 0x80000000 /* reg is standard reg */ +#define CS_CFG_REG_RESOURCE 0x40000000 /* reg is a resource */ +#define CS_CFG_REG_VAL_PARAM 0x08000000 /* reg value uses param */ +#define CS_CFG_REG_VAL_MASK 0x04000000 /* reg value bit masked */ +#define CS_CFG_REG_VAL_64BIT 0x02000000 /* reg value 64 bit */ +#define CS_CFG_REG_VAL_SAVE 0x01000000 /* reg value save on disable */ +#define CS_CFG_REG_ID_MASK 0x00000FFF /* reg offset / id in device */ +#define CS_CFG_REG_DEV_MASK 0x00FFF000 /* device specific flags */ + +/* + * flags defining what device class a feature will match to when processing a + * system configuration - used by config data and devices. + */ +#define CS_CFG_MATCH_CLASS_SRC_ALL 0x0001 /* match any source */ +#define CS_CFG_MATCH_CLASS_SRC_ETM4 0x0002 /* match any ETMv4 device */ +#define CS_CFG_MATCH_CLASS_CTI_ALL 0x0004 /* match any CTI device */ +#define CS_CFG_MATCH_CLASS_CTI_CPU 0x0008 +#define CS_CFG_MATCH_CLASS_CTI_SYS 0x0010 + +/* flags defining device instance matching - used in config data. */ +#define CS_CFG_MATCH_INST_ANY 0x80000000 /* any instance of a class */ +#define CS_CFG_MATCH_INST_AMBA_DEVICE 0x40000000 /* specific amba device */ + +/* + * Limit number of presets in a configuration + * This is related to the number of bits (4) we use to select the preset on + * the perf command line. Preset 0 is always none selected. + * See PMU_FORMAT_ATTR(preset, "config:0-3") in coresight-etm-perf.c + */ +#define CS_CFG_CONFIG_PRESET_MAX 15 + + +/** + * Parameter descriptor for a device feature. + * + * @name: Name of parameter. + * @value: Initial or default value. + */ +struct cscfg_parameter_desc { + const char *name; + u64 value; +}; + +/** + * Representation of register value. + * + * Supports full 64 bit register value, or 32 bit value with optional mask + * value. + * + * @flags: define value usage as 32bit, 32bit+mask or 64bit. + * @val64: 64 bit value. + * @val32: 32 bit value. + * @mask32: 32 bit mask when using 32 bit value to access device register. + */ +struct cscfg_regval { + u32 flags; + union { + u64 val64; + struct { + u32 val32; + u32 mask32; + }; + }; +}; + + +/** + * Device feature descriptor - combination of registers and parameters to + * program a device to implement a specific complex function. + * + * @name: feature name. + * @brief: brief description of the feature. + * @item: List entry. + * @match_flags: matching information if loading into a device + * @nr_params: number of parameters used. + * @params: array of parameters used. + * @nr_regs: number of registers used. + * @reg: array of registers used. + */ +struct cscfg_feature_desc { + const char *name; + const char *brief; + struct list_head item; + u32 match_flags; + int nr_params; + struct cscfg_parameter_desc *params; + int nr_regs; + struct cscfg_regval *regs; +}; + +/** + * Device / feature matching information. + * + * Used by loading configurations to define which class or specific devices + * they want to match used features to, and registered devices to specify which + * matching class and information they support. + * The load process uses these matching pairs to load feature instances into + * matching devices. + * + * @match_flags: used to match to a particular class of device. + * @dev_name: used to match to a particular device instance on the system. + * + */ +struct cscfg_match_info { + u32 match_flags; + /* unique device name (e.g. amba bus name) for specific device match */ + const char *dev_name; +}; + +/** + * Descriptor for features referenced by a configuration. + * + * @name: name of feature to use. Match against the @name in struct + * cscfg_feature_desc. + * @nr_params: number of parameters the feature has. + * @match: match info for the feature when used in this configuration - + * may be all devices of a class or a specific device in that class. + */ +struct cscfg_config_feat_ref { + const char *name; + int nr_params; + struct cscfg_match_info match; +}; + +/** + * Configuration descriptor - describes selectable system configuration. + * + * A configuration describes device features in use, and may provide preset + * values for the parameters in those features. + * + * A single set of presets is the sum of the parameters declared by + * all the features in use - this value is @nr_total_params. + * + * @name: name of the configuration - used for selection. + * @brief: description of the purpose of the configuration. + * @item: list entry. + * @nr_refs: Number of features used in this configuration. + * @refs: references to features used in this configuration.. + * @nr_presets: Number of sets of presets supplied by this configuration. + * @nr_total_params: Sum of all parameters declared by used features + * @presets: Array of preset values. + * + */ +struct cscfg_config_desc { + const char *name; + const char *brief; + struct list_head item; + int nr_refs; + struct cscfg_config_feat_ref *refs; + int nr_presets; + int nr_total_params; + const u64 *presets; /* nr_presets * nr_total_params */ +}; + +#endif /* _CORESIGHT_CORESIGHT_CONFIG_H */ diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c index 29c83eac3106..481d2b7b6b6f 100644 --- a/drivers/hwtracing/coresight/coresight-core.c +++ b/drivers/hwtracing/coresight/coresight-core.c @@ -21,6 +21,7 @@ #include "coresight-etm-perf.h" #include "coresight-priv.h" +#include "coresight-syscfg.h" static DEFINE_MUTEX(coresight_mutex); @@ -1675,13 +1676,22 @@ static int __init coresight_init(void) ret = etm_perf_init(); if (ret) - bus_unregister(&coresight_bustype); + goto exit_bus_unregister; + /* initialise the coresight syscfg API */ + ret = cscfg_init(); + if (!ret) + return 0; + + etm_perf_exit(); +exit_bus_unregister: + bus_unregister(&coresight_bustype); return ret; } static void __exit coresight_exit(void) { + cscfg_exit(); etm_perf_exit(); bus_unregister(&coresight_bustype); } diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c index bdc34ca449f7..a608081bd446 100644 --- a/drivers/hwtracing/coresight/coresight-etm-perf.c +++ b/drivers/hwtracing/coresight/coresight-etm-perf.c @@ -627,7 +627,7 @@ int __init etm_perf_init(void) return ret; } -void __exit etm_perf_exit(void) +void etm_perf_exit(void) { perf_pmu_unregister(&etm_pmu); } diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.h b/drivers/hwtracing/coresight/coresight-etm-perf.h index 3e4f2ad5e193..29d90dfeba31 100644 --- a/drivers/hwtracing/coresight/coresight-etm-perf.h +++ b/drivers/hwtracing/coresight/coresight-etm-perf.h @@ -83,6 +83,6 @@ static inline void *etm_perf_sink_config(struct perf_output_handle *handle) #endif /* CONFIG_CORESIGHT */ int __init etm_perf_init(void); -void __exit etm_perf_exit(void); +void etm_perf_exit(void); #endif diff --git a/drivers/hwtracing/coresight/coresight-syscfg.c b/drivers/hwtracing/coresight/coresight-syscfg.c new file mode 100644 index 000000000000..6f89541af7a0 --- /dev/null +++ b/drivers/hwtracing/coresight/coresight-syscfg.c @@ -0,0 +1,247 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 Linaro Limited, All rights reserved. + * Author: Mike Leach + */ + +#include + +#include "coresight-config.h" +#include "coresight-syscfg.h" + +/* + * cscfg_ API manages configurations and features for the entire coresight + * infrastructure. + * + * It allows the loading of configurations and features, and loads these into + * coresight devices as appropriate. + */ + +static DEFINE_MUTEX(cscfg_mutex); + +/* only one of these */ +static struct cscfg_api_data cscfg_data; + +/* get reference to cscfg device */ +struct device *to_device_cscfg(void); + +/* load features and configuations into the lists */ + +/* check feature list for a named feature - call with mutex locked. */ +static bool cscfg_match_list_feat(const char *name) +{ + struct cscfg_feature_desc *curr_item; + + list_for_each_entry(curr_item, &cscfg_data.feat_list, item) { + if (strcmp(curr_item->name, name) == 0) + return true; + } + return false; +} + +/* check all feat needed for cfg are in the list - call with mutex locked. */ +static int cscfg_check_feat_for_cfg(struct cscfg_config_desc *cfg_desc) +{ + int i; + + for (i = 0; i < cfg_desc->nr_refs; i++) + if (!cscfg_match_list_feat(cfg_desc->refs[i].name)) + return -EINVAL; + return 0; +} + +/* + * load feature - add to feature list. + */ +static int cscfg_load_feat(struct cscfg_feature_desc *feat_desc) +{ + list_add(&feat_desc->item, &cscfg_data.feat_list); + + return 0; +} + +/* + * load config into the system - validate used features exist then add to + * config list. + */ +static int cscfg_load_config(struct cscfg_config_desc *cfg_desc) +{ + int err; + + /* validate features are present */ + err = cscfg_check_feat_for_cfg(cfg_desc); + if (err) + return err; + + list_add(&cfg_desc->item, &cscfg_data.config_list); + + return 0; +} + +/* + * External API function to load feature and config sets. + * Take a 0 terminated array of feature descriptors and/or configuration + * descriptors and load into the system. + * Features are loaded first to ensure configuration dependencies can be met. + */ +int cscfg_load_config_sets(struct cscfg_config_desc **cfg_descs, + struct cscfg_feature_desc **feat_descs) +{ + int err, i = 0; + + mutex_lock(&cscfg_mutex); + + /* load features first */ + if (feat_descs) { + while (feat_descs[i]) { + err = cscfg_load_feat(feat_descs[i]); + if (err) { + pr_err("coresight-syscfg: Failed to load feature %s\n", + feat_descs[i]->name); + goto do_unlock; + } + i++; + } + } + + /* next any configurations to check feature dependencies */ + i = 0; + if (cfg_descs) { + while (cfg_descs[i]) { + err = cscfg_load_config(cfg_descs[i]); + if (err) { + pr_err("coresight-syscfg: Failed to load configuration %s\n", + cfg_descs[i]->name); + goto do_unlock; + } + i++; + } + } + +do_unlock: + mutex_unlock(&cscfg_mutex); + return err; +} +EXPORT_SYMBOL_GPL(cscfg_load_config_sets); + +/* Initialise system configuration management driver. */ +/* only one of these */ +static struct cscfg_device *cscfg_dev; + +/* + * We have a separate coresight-config bus for the config device so it does + * not appear on the main coresight bus and affect device searches on that bus. + */ +static struct bus_type cscfg_bus_type = { + .name = "coresight-config", +}; + +struct device *to_device_cscfg(void) +{ + return cscfg_dev ? &cscfg_dev->dev : NULL; +} + +/* Must have a release function or the kernel will complain on module unload */ +void cscfg_dev_release(struct device *dev) +{ + kfree(cscfg_dev); + cscfg_dev = NULL; +} + +int cscfg_create_device(void) +{ + struct device *dev; + int err = -ENOMEM; + + mutex_lock(&cscfg_mutex); + if (cscfg_dev) { + err = -EINVAL; + goto create_dev_exit_unlock; + } + + cscfg_dev = kzalloc(sizeof(struct cscfg_device), GFP_KERNEL); + if (!cscfg_dev) + goto create_dev_exit_unlock; + + /* setup the device */ + dev = to_device_cscfg(); + dev->bus = &cscfg_bus_type; + dev->parent = &platform_bus; + dev->release = cscfg_dev_release; + dev->init_name = "system_cfg"; + cscfg_dev->cfg_data = &cscfg_data; + + err = device_register(dev); + if (err) + cscfg_dev_release(dev); + +create_dev_exit_unlock: + mutex_unlock(&cscfg_mutex); + return err; +} + +void cscfg_clear_device(void) +{ + mutex_lock(&cscfg_mutex); + device_unregister(to_device_cscfg()); + mutex_unlock(&cscfg_mutex); +} + +/* driver initialisation */ +static struct cscfg_driver cs_config_driver = { + .drv = { + .name = "cs-syscfg-drv", + .owner = THIS_MODULE, + .suppress_bind_attrs = true, + }, +}; + +int __init cscfg_driver_init(void) +{ + cs_config_driver.drv.bus = &cscfg_bus_type; + return driver_register(&cs_config_driver.drv); +} + +void cscfg_driver_exit(void) +{ + driver_unregister(&cs_config_driver.drv); +} + +/* Initialise system config management API */ +int __init cscfg_init(void) +{ + int err = 0; + + err = bus_register(&cscfg_bus_type); + if (err) + return err; + + err = cscfg_driver_init(); + if (err) + goto exit_bus_unregister; + + err = cscfg_create_device(); + if (err) + goto exit_drv_unregister; + + INIT_LIST_HEAD(&cscfg_data.dev_list); + INIT_LIST_HEAD(&cscfg_data.feat_list); + INIT_LIST_HEAD(&cscfg_data.config_list); + cscfg_data.nr_csdev = 0; + + dev_info(to_device_cscfg(), "CoreSight Configuration manager initialised"); + return 0; + +exit_drv_unregister: + cscfg_driver_exit(); +exit_bus_unregister: + bus_unregister(&cscfg_bus_type); + return err; +} + +void __exit cscfg_exit(void) +{ + cscfg_clear_device(); + cscfg_driver_exit(); + bus_unregister(&cscfg_bus_type); +} diff --git a/drivers/hwtracing/coresight/coresight-syscfg.h b/drivers/hwtracing/coresight/coresight-syscfg.h new file mode 100644 index 000000000000..5a7896426eab --- /dev/null +++ b/drivers/hwtracing/coresight/coresight-syscfg.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Coresight system configuration driver. + */ + +#ifndef CORESIGHT_SYSCFG_H +#define CORESIGHT_SYSCFG_H + +#include +#include + +#include "coresight-config.h" + +/** + * System configuration API data. + * + * @dev_list: List of other coresight devices registered with this device. + * @feat_list: List of features to load into registered devices. + * @config_list:List of system configurations to load into registered devices. + * @nr_csdev: Number of registered devices with the cscfg system + */ +struct cscfg_api_data { + struct list_head dev_list; + struct list_head feat_list; + struct list_head config_list; + int nr_csdev; +}; + +/* internal core operations for cscfg */ +int __init cscfg_init(void); +void __exit cscfg_exit(void); + +/* syscfg external API */ +int cscfg_load_config_sets(struct cscfg_config_desc **cfg_descs, + struct cscfg_feature_desc **feat_descs); + +/* system configuration device driver and API */ +/** + * System configuration device. + * + * Need a device to 'own' some coresight system wide sysfs entries in + * perf events etc. + * + * @dev: The device. + * @cfg_data: A reference to the configuration and feature lists + */ +struct cscfg_device { + struct device dev; + struct cscfg_api_data *cfg_data; +}; + +/* basic device driver */ +struct cscfg_driver { + struct device_driver drv; +}; + +#endif /* CORESIGHT_SYSCFG_H */ From patchwork Fri Oct 30 17:56:48 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Leach X-Patchwork-Id: 11870451 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 63FB4C00A89 for ; Fri, 30 Oct 2020 17:57:55 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id BA2FC20A8B for ; Fri, 30 Oct 2020 17:57:54 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="esYTw1yw"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="Y93tkZGW" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org BA2FC20A8B Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:MIME-Version:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:References:In-Reply-To:Message-Id:Date:Subject:To: From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=Ir6XtjdwtyyfXCwHVljdQ58OtuGorj86MTL/y1pGLj8=; b=esYTw1ywkfUnoK/zE/zpJv6yk+ +P6oTBt+GTN9EKQy00gv1XuZpmOgzAYaqYKajPGaW/1mX5KrInXDgBaZB5MBi5CDDdvQk2KYTdqS9 aSfT03pLwgYmXf9AU1BqwgNFLAcoTP22ZMwu6yLlrBcrUZSQDkzc5wiCc9OssR96h9TrLTZQSkV7l AnwgCQsX7VNurRqbmY5OMFcDBfwr4ICAVSxv3vwxeAeJmXF2UNF1KiTrj2tY6dxSGQxkA5qc4WHXG UFHWd+Hv8fNOsn6Ib4KYEmo6JWLhWR+mGxKYE40e8PECqWkZdmbSG/gIdjQc26pqTGA/RtoUSi24B FGIJVnfg==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kYYeM-0003pG-Ld; Fri, 30 Oct 2020 17:57:18 +0000 Received: from mail-wr1-x443.google.com ([2a00:1450:4864:20::443]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kYYe5-0003kK-Qy for linux-arm-kernel@lists.infradead.org; Fri, 30 Oct 2020 17:57:10 +0000 Received: by mail-wr1-x443.google.com with SMTP id b8so7446200wrn.0 for ; Fri, 30 Oct 2020 10:57:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=oyYWMIM5f1MX2n6Img4sXl2Fd8fKcDYRfoz2TJOtZT8=; b=Y93tkZGW52dGJu/2YiH8dPyKJ7sfEchd/gmd3z8UhTWR4LVmCD0zqZNZHAoEeC6lJv LymSLFR1dCnRHE5fZpeLKIO0fsQSp7ARZN7TTUKOjIK13661Rpl0bwB2mD4lEWyVxJ16 oJ9ZhmJFUg4VPFh6qYFTj+4dp1XEUpVFZ+V6B3vQrpveA8MHz0FFDxh4w4oftMYsNRdo ovA0pu3YI2d2JcI/bVubz/LvdIK4NRIJ2kZatsdTI20r5wEyywwLQ/9ucvNMIQdS0XLj MEqb6dXwQZKZW/G0MQxko7/okLLT9Jv5xFzaAJxurxYYUuuwkihd2xfF/isW2vqEAILd L3AQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=oyYWMIM5f1MX2n6Img4sXl2Fd8fKcDYRfoz2TJOtZT8=; b=U0TkfMBRxU/XX4O12G1veb5RjfRp/r2CNc+CUvqvKy+nVyeiPe6HRUMeitdkYvcQdE CVucxKkwVJKSmTusoUPHD4yTTb20OJL17xA8qtUQL2hX7XrPk1TSr5h5erDLanM/5QJl hf1N+2hzYl2aWz/HcwEPoMNQSPXg6izKGbVnmMznN56Pe/z5TijMb7Tz6odWC1PgL/B9 +nC1+nfpL4+DKPa6QrCUxjT9QyZh2K9asaBXpJ/wfF2HkUOJLR2efJrpVmLkSCbyP+ho Zq3njJSJL0RnbT6uyCxVvYm3rSqW4O7orelh/cjQz6XnSwuX87CJMpmtChJTiBVAC1Vc IMVg== X-Gm-Message-State: AOAM5309eRORRDw1BjXQKIsFz7egUEo4P/RHNjCQoMqefRYu6LpNSXWu ByPngEvw+zWx8WpbkVFdUNXC0nHp1CQYcA== X-Google-Smtp-Source: ABdhPJzkM2nrUmjI4wvFMUGolrWOhl3qaTi4qcdP7qoi/Ff/FyHLwZ7EhHa8qHJff47ek4Ib34/Isw== X-Received: by 2002:adf:bd86:: with SMTP id l6mr4771016wrh.205.1604080620174; Fri, 30 Oct 2020 10:57:00 -0700 (PDT) Received: from linaro.org ([2a00:23c5:6801:1801:4964:83f8:d2e7:f2c9]) by smtp.gmail.com with ESMTPSA id o129sm5615563wmb.25.2020.10.30.10.56.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 30 Oct 2020 10:56:59 -0700 (PDT) From: Mike Leach To: linux-arm-kernel@lists.infradead.org, coresight@lists.linaro.org, mathieu.poirier@linaro.org Subject: [RFC PATCH v3 2/9] coresight: syscfg: Add registration and feature loading for cs devices Date: Fri, 30 Oct 2020 17:56:48 +0000 Message-Id: <20201030175655.30126-3-mike.leach@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201030175655.30126-1-mike.leach@linaro.org> References: <20201030175655.30126-1-mike.leach@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201030_135701_977951_1CD62394 X-CRM114-Status: GOOD ( 35.86 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: yabinc@google.com, Mike Leach , suzuki.poulose@arm.com MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org 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 --- .../hwtracing/coresight/coresight-config.h | 120 ++++++ .../hwtracing/coresight/coresight-syscfg.c | 346 ++++++++++++++++++ .../hwtracing/coresight/coresight-syscfg.h | 20 + include/linux/coresight.h | 7 + 4 files changed, 493 insertions(+) diff --git a/drivers/hwtracing/coresight/coresight-config.h b/drivers/hwtracing/coresight/coresight-config.h index 0d9ae1dc4517..8fd7ff991ced 100644 --- a/drivers/hwtracing/coresight/coresight-config.h +++ b/drivers/hwtracing/coresight/coresight-config.h @@ -167,4 +167,124 @@ struct cscfg_config_desc { const u64 *presets; /* nr_presets * nr_total_params */ }; +/** + * config register instance - part of a loaded feature. + * maps register values to csdev driver structures + * + * @value: value to use when setting feature on device / store for + * readback of volatile values. + * @drv_store: pointer to internal driver element used to set the value + * in hardware. + */ +struct cscfg_reg_csdev { + struct cscfg_regval 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; +}; + +/** + * cscfg_feat_ops - standard operations for loaded features. + * + * CS config core provides basic defaults for these, which can be overridden by + * device specific versions. + * + * @set_on_enable: Set the feature on the driver before hw enable. + * @save_on_disable: Save any volatile register values after hw disable. + * @reset: Reset feature to default values. + */ +struct cscfg_feat_ops { + int (*set_on_enable)(struct cscfg_feature_csdev *feat, const bool force_set); + void (*save_on_disable)(struct cscfg_feature_csdev *feat, const bool force_save); + void (*reset)(struct cscfg_feature_csdev *feat); +}; + +/** + * 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.. + * @enabled: feature is enabled on this device. + * @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 + * @ops: standard ops to enable and disable features on devices. + */ +struct cscfg_feature_csdev { + const struct cscfg_feature_desc *desc; + struct coresight_device *csdev; + struct list_head node; + spinlock_t *csdev_spinlock; + bool enabled; + int nr_params; + struct cscfg_parameter_csdev *params; + int nr_regs; + struct cscfg_reg_csdev *regs; + struct cscfg_feat_ops ops; +}; + +/** + * 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 + * @id_hash: hash value of configuration name used for selection. + * @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; + unsigned long id_hash; + 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 + * 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 */ diff --git a/drivers/hwtracing/coresight/coresight-syscfg.c b/drivers/hwtracing/coresight/coresight-syscfg.c index 6f89541af7a0..53bc1d551171 100644 --- a/drivers/hwtracing/coresight/coresight-syscfg.c +++ b/drivers/hwtracing/coresight/coresight-syscfg.c @@ -27,6 +27,198 @@ struct device *to_device_cscfg(void); /* load features and configuations into the lists */ +/* get name feature instance from a coresight device list of features */ +static struct cscfg_feature_csdev * +cscfg_get_feat_csdev(struct coresight_device *csdev, const char *name) +{ + struct cscfg_feature_csdev *feat = NULL; + + list_for_each_entry(feat, &csdev->feat_list, node) { + if (strcmp(feat->desc->name, name) == 0) + return feat; + } + return NULL; +} + +/* allocate the device config instance - with max number of used features */ +static struct cscfg_config_csdev * +cscfg_alloc_csdev_cfg(struct coresight_device *csdev, int nr_feats) +{ + struct cscfg_config_csdev *dev_cfg = NULL; + struct device *dev = csdev->dev.parent; + + /* this is being allocated using the devm for the coresight device */ + dev_cfg = devm_kzalloc(dev, sizeof(struct cscfg_config_csdev), GFP_KERNEL); + if (!dev_cfg) + return NULL; + + dev_cfg->csdev = csdev; + dev_cfg->feats = devm_kcalloc(dev, nr_feats, + sizeof(struct cscfg_feature_csdev *), + GFP_KERNEL); + if (!dev_cfg->feats) + dev_cfg = NULL; + return dev_cfg; +} + +/* check match info between used feature from the config and a regisered device */ +static bool cscfg_match_feat_info(struct cscfg_match_info *used_cmp, + struct cscfg_match_info *reg_dev) +{ + /* if flags don't match then fail early */ + if (!(used_cmp->match_flags & reg_dev->match_flags)) + return false; + + /* if input used_cmp has a name, then check this too */ + if (used_cmp->dev_name) { + if (strcmp(used_cmp->dev_name, reg_dev->dev_name) != 0) + return false; + } + return true; +} + +/* Load a config into a device if there are feature matches between config and device */ +static int cscfg_add_csdev_cfg(struct coresight_device *csdev, + struct cscfg_match_info *match_info, + struct cscfg_config_desc *cfg_desc) +{ + struct cscfg_config_csdev *dev_cfg = NULL; + struct cscfg_config_feat_ref *feat_ref; + struct cscfg_feature_csdev *feat; + 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) + list_add(&dev_cfg->node, &csdev->syscfg_list); + + 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_data.dev_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 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 (feat->nr_params) { + feat->params = devm_kcalloc(dev, feat->nr_params, + sizeof(struct cscfg_parameter_csdev), + GFP_KERNEL); + if (!feat->params) + return NULL; + } + + /* always have registers to program */ + 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; + for (i = 0; i < feat->nr_params; i++) + feat->params[i].feat = feat; + + 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 */ + spin_lock(&csdev->cfg_lock); + list_add(&feat_csdev->node, &csdev->feat_list); + spin_unlock(&csdev->cfg_lock); + + 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_data.dev_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) { @@ -55,6 +247,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_data.feat_list); return 0; @@ -73,6 +272,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_data.config_list); return 0; @@ -124,6 +328,148 @@ 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_info *info) +{ + struct cscfg_config_desc *curr_item; + int err = 0; + + list_for_each_entry(curr_item, &cscfg_data.config_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_info *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_data.feat_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_info *info, + struct cscfg_csdev_feat_ops *ops) +{ + struct cscfg_csdev_register *list_entry; + const char *name = NULL; + + /* allocate the list entry structure */ + list_entry = kzalloc(sizeof(struct cscfg_csdev_register), GFP_KERNEL); + if (!list_entry) + return -ENOMEM; + if (info->dev_name) { + name = kstrdup(info->dev_name, GFP_KERNEL); + if (!name) { + kfree(list_entry); + return -ENOMEM; + } + } + + list_entry->csdev = csdev; + list_entry->match_info.match_flags = info->match_flags; + list_entry->match_info.dev_name = name; + list_entry->ops.load_feat = ops->load_feat; + list_add(&list_entry->item, &cscfg_data.dev_list); + + INIT_LIST_HEAD(&csdev->feat_list); + INIT_LIST_HEAD(&csdev->syscfg_list); + spin_lock_init(&csdev->cfg_lock); + cscfg_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_data.dev_list, item) { + if (curr_item->csdev == csdev) { + list_del(&curr_item->item); + kfree(curr_item->match_info.dev_name); + kfree(curr_item); + cscfg_data.nr_csdev--; + break; + } + } +} + +/* register a coresight device with the syscfg api */ +int cscfg_register_csdev(struct coresight_device *csdev, + struct cscfg_match_info *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_data.dev_list, item) { + if (curr_item->csdev == csdev) { + list_del(&curr_item->item); + kfree(curr_item->match_info.dev_name); + kfree(curr_item); + cscfg_data.nr_csdev--; + break; + } + } + mutex_unlock(&cscfg_mutex); +} +EXPORT_SYMBOL_GPL(cscfg_unregister_csdev); + /* Initialise system configuration management driver. */ /* only one of these */ static struct cscfg_device *cscfg_dev; diff --git a/drivers/hwtracing/coresight/coresight-syscfg.h b/drivers/hwtracing/coresight/coresight-syscfg.h index 5a7896426eab..ecf4aac7d712 100644 --- a/drivers/hwtracing/coresight/coresight-syscfg.h +++ b/drivers/hwtracing/coresight/coresight-syscfg.h @@ -26,6 +26,22 @@ struct cscfg_api_data { int nr_csdev; }; +/** + * 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_info match_info; + struct cscfg_csdev_feat_ops ops; + struct list_head item; +}; + /* internal core operations for cscfg */ int __init cscfg_init(void); void __exit cscfg_exit(void); @@ -33,6 +49,10 @@ void __exit cscfg_exit(void); /* syscfg external API */ int cscfg_load_config_sets(struct cscfg_config_desc **cfg_descs, struct cscfg_feature_desc **feat_descs); +int cscfg_register_csdev(struct coresight_device *csdev, + struct cscfg_match_info *info, + struct cscfg_csdev_feat_ops *ops); +void cscfg_unregister_csdev(struct coresight_device *csdev); /* system configuration device driver and API */ /** diff --git a/include/linux/coresight.h b/include/linux/coresight.h index 7d3c87e5b97c..bade9e8ac20c 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -189,6 +189,9 @@ struct coresight_sysfs_link { * @nr_links: number of sysfs links created to other components from this * device. These will appear in the "connections" group. * @has_conns_grp: Have added a "connections" group for sysfs links. + * @feat_list: List of complex feature programming added to the device. + * @syscfg_list: List of system configurations added to the device. + * @cfg_lock: spinlock to protect feature and config lists for this device. */ struct coresight_device { struct coresight_platform_data *pdata; @@ -209,6 +212,10 @@ struct coresight_device { int nr_links; bool has_conns_grp; bool ect_enabled; /* true only if associated ect device is enabled */ + /* complex config and feature lists */ + struct list_head feat_list; + struct list_head syscfg_list; + spinlock_t cfg_lock; }; /* From patchwork Fri Oct 30 17:56:49 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Leach X-Patchwork-Id: 11870455 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id CFFDAC00A89 for ; Fri, 30 Oct 2020 17:59:06 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 2C7BB20A8B for ; Fri, 30 Oct 2020 17:59:05 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="PUHSkFWx"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="zS38GLDx" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 2C7BB20A8B Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:MIME-Version:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:References:In-Reply-To:Message-Id:Date:Subject:To: From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=1UrVtSl6VPpW9+Psg1z1Xi7TJ7ubkQTYL+VPSBtrVVo=; b=PUHSkFWxoh7D+UNcZvb+/aO2sd 5sMGgdsxXBB69idEFvw97kV9f5lUBDVC3d6p7b+txueH+XaBMAisWtsTLmXUnQFBD08sUEV9QBv2N 9F5LL/8vTG9PR5ddx08dBa+etocOJmvuyyfmU6J6aX9q3rY4dIVvJDBif5CUqKEGDL+gEiHVvLUqv +Ycj2kcQFOzybH+q1cFg/yBMxXQTCG3vxl+pV1h+c+voX1PyVea7eA0joaMP1V3PCvYNVZ5U7Lxld vqNfe5Y9AMTldBulAsyOXJ8EHwTpSCpHkDRx5PnF5mfYcDUBpp8UWcoAXQku6RxD/s5Gvf1cRPJMG npTV5neg==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kYYeJ-0003oI-Ut; Fri, 30 Oct 2020 17:57:16 +0000 Received: from mail-wm1-x343.google.com ([2a00:1450:4864:20::343]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kYYe6-0003kp-OY for linux-arm-kernel@lists.infradead.org; Fri, 30 Oct 2020 17:57:09 +0000 Received: by mail-wm1-x343.google.com with SMTP id c9so2106344wml.5 for ; Fri, 30 Oct 2020 10:57:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=zlPEe0g6hLUW6AhXvGlEPvuQ8eVQkTzCd1Py3AVwas0=; b=zS38GLDxssXK9aF8wXHm9vrRD1uB7fpsBbMIz+u+i87IQtd57iRH5xSkQZHuh3v7a1 QZcKDnmr1eMvvFTJ5/UgrVtGX4CW9e741hAuvkO0WUcJ/DXtwi93S5lU1RKjYb0UPTa3 +kgau2ZYXsvoLmdC2JAbUhmL3e9t0Gnz8xaU7mugUBI1EgoRhwf45sqMTDnWZqxkz0Xf 9dQcCi6g/6H0+84nj20fvtR4BH+8y34iTGD/ISu6/Wb4SCdwHnxhASGy/zy53lui7rrU 6ChBIZ1KReRhbm/iKNrnJ5q2/+CKUnO7ywk0TvWNRNW7LhNfK9JC6Cxq9HyDwV1xOJFi yycw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=zlPEe0g6hLUW6AhXvGlEPvuQ8eVQkTzCd1Py3AVwas0=; b=J/+xCOTWcFWgaQZ5pmP6RysV9ISea+1glypiukFbAtoq5Svk7vTiruAGsPJ/AV7rRo a3diE0EUv9WV5w/e2Pau0q9ve20aNCdJwc2uzXtDa5OJJLE3k3E+oEnws5UJke9n280D sCpA+427nSUNBntiQ81vk7nbm4jkIY7RoAIa9uvOOqjAoz05hGwpHiiH56x4Tg3Rc74B wA1YlWxoqgohzdlCQD0FnDCsDsPHPiprE2i8ZyYsMX7LtSc4Q0qCK+M22kPMVzTasdK2 aD/6H9D+ffTFLbwsDj5DDw0WvDKhogueU5j2aKJopqZCTPLVY+r8UAmJQQ3t1H8k35MY qoRA== X-Gm-Message-State: AOAM533kynOXXihTNDCI//61dkdWL/tsKIAvPTGMPbkGhQG3Z2SXhlnl wwOvdTvPfVXthZKvO9gtJSeP/ZRM/3rKAQ== X-Google-Smtp-Source: ABdhPJy3x45ZzNQZTbGvrcGuns96zlGQDXSQQpQZiglf4qPYkPqzcHckgEIxekhU7RAeVj8AOA3ZbQ== X-Received: by 2002:a1c:56c1:: with SMTP id k184mr3934895wmb.14.1604080621260; Fri, 30 Oct 2020 10:57:01 -0700 (PDT) Received: from linaro.org ([2a00:23c5:6801:1801:4964:83f8:d2e7:f2c9]) by smtp.gmail.com with ESMTPSA id o129sm5615563wmb.25.2020.10.30.10.57.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 30 Oct 2020 10:57:00 -0700 (PDT) From: Mike Leach To: linux-arm-kernel@lists.infradead.org, coresight@lists.linaro.org, mathieu.poirier@linaro.org Subject: [RFC PATCH v3 3/9] coresight: config: Add configuration and feature generic functions Date: Fri, 30 Oct 2020 17:56:49 +0000 Message-Id: <20201030175655.30126-4-mike.leach@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201030175655.30126-1-mike.leach@linaro.org> References: <20201030175655.30126-1-mike.leach@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201030_135702_911304_3ABFE9A5 X-CRM114-Status: GOOD ( 31.28 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: yabinc@google.com, Mike Leach , suzuki.poulose@arm.com MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org 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 --- drivers/hwtracing/coresight/Makefile | 2 +- .../hwtracing/coresight/coresight-config.c | 362 ++++++++++++++++++ .../hwtracing/coresight/coresight-config.h | 14 + .../hwtracing/coresight/coresight-syscfg.c | 4 + 4 files changed, 381 insertions(+), 1 deletion(-) create mode 100644 drivers/hwtracing/coresight/coresight-config.c diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile index 4ce854c434b1..daad9f103a78 100644 --- a/drivers/hwtracing/coresight/Makefile +++ b/drivers/hwtracing/coresight/Makefile @@ -4,7 +4,7 @@ # obj-$(CONFIG_CORESIGHT) += coresight.o coresight-y := coresight-core.o coresight-etm-perf.o coresight-platform.o \ - coresight-sysfs.o coresight-syscfg.o + coresight-sysfs.o coresight-syscfg.o coresight-config.o obj-$(CONFIG_CORESIGHT_LINK_AND_SINK_TMC) += coresight-tmc.o coresight-tmc-y := coresight-tmc-core.o coresight-tmc-etf.o \ coresight-tmc-etr.o diff --git a/drivers/hwtracing/coresight/coresight-config.c b/drivers/hwtracing/coresight/coresight-config.c new file mode 100644 index 000000000000..d911e0f083c1 --- /dev/null +++ b/drivers/hwtracing/coresight/coresight-config.c @@ -0,0 +1,362 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright(C) 2020 Linaro Limited. All rights reserved. + * Author: Mike Leach + */ + +#include +#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; + u32 tmp32; + + if (!(reg->value.flags & CS_CFG_REG_VAL_64BIT)) { + if (reg->value.flags & CS_CFG_REG_VAL_MASK) { + tmp32 = *p_val32; + tmp32 &= ~reg->value.mask32; + tmp32 |= reg->value.val32 & reg->value.mask32; + *p_val32 = tmp32; + } else + *p_val32 = reg->value.val32; + } else + *((u64 *)reg->drv_store) = reg->value.val64; +} + +/* + * 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.flags & CS_CFG_REG_VAL_SAVE)) + return; + if (reg->value.flags & CS_CFG_REG_VAL_64BIT) + reg->value.val64 = *(u64 *)(reg->drv_store); + else + reg->value.val32 = *(u32 *)(reg->drv_store); +} + +static inline void cscfg_init_reg_val(struct cscfg_reg_csdev *reg, + const struct cscfg_regval *desc) +{ + reg->value.val64 = desc->val64; +} + +static inline void cscfg_init_reg_flags(struct cscfg_reg_csdev *reg, + const struct cscfg_regval *desc) +{ + reg->value.flags = desc->flags; +} + +static void cscfg_init_reg_param(struct cscfg_parameter_csdev *param, + struct cscfg_reg_csdev *reg) +{ + param->reg = reg; + param->val64 = reg->value.flags & CS_CFG_REG_VAL_64BIT; + + if (param->val64) + param->reg->value.val64 = param->current_value; + else + param->reg->value.val32 = (u32)param->current_value; +} + +/* default set - will set values without resource checking */ +static int cscfg_set_on_enable(struct cscfg_feature_csdev *feat, const bool force_set) +{ + int i; + + spin_lock(feat->csdev_spinlock); + if (feat->enabled || force_set) { + for (i = 0; i < feat->nr_regs; i++) + cscfg_set_reg(&feat->regs[i]); + } + dev_dbg(&feat->csdev->dev, "Feature %s: %s", feat->desc->name, + feat->enabled || force_set ? "Set enabled" : "Skip disabled"); + spin_unlock(feat->csdev_spinlock); + return 0; +} + +static void cscfg_save_on_disable(struct cscfg_feature_csdev *feat, const bool force_save) +{ + int i; + + spin_lock(feat->csdev_spinlock); + if (feat->enabled || force_save) { + for (i = 0; i < feat->nr_regs; i++) + cscfg_save_reg(&feat->regs[i]); + } + dev_dbg(&feat->csdev->dev, "Feature %s: %s", feat->desc->name, + feat->enabled || force_save ? "Save disabled" : "Skip disabled"); + spin_unlock(feat->csdev_spinlock); +} + +/* default reset - restore default values, disable feature */ +static void cscfg_reset_feat(struct cscfg_feature_csdev *feat) +{ + struct cscfg_reg_csdev *reg; + struct cscfg_regval *reg_desc; + struct cscfg_parameter_csdev *param; + int i; + + spin_lock(feat->csdev_spinlock); + feat->enabled = false; + + /* + * 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 = &feat->regs[i]; + cscfg_init_reg_flags(reg, reg_desc); + + /* check if reg set from a parameter otherwise desc default */ + if (reg_desc->flags & CS_CFG_REG_VAL_PARAM) { + param = &feat->params[reg_desc->val32]; + cscfg_init_reg_param(param, reg); + } else + cscfg_init_reg_val(reg, reg_desc); + } + spin_unlock(feat->csdev_spinlock); +} + +void cscfg_set_def_ops(struct cscfg_feature_csdev *feat) +{ + feat->ops.set_on_enable = cscfg_set_on_enable; + feat->ops.save_on_disable = cscfg_save_on_disable; + feat->ops.reset = cscfg_reset_feat; +} + +int cscfg_csdev_set_enabled_feats(struct coresight_device *csdev) +{ + struct cscfg_feature_csdev *feat; + int err = 0; + + spin_lock(&csdev->cfg_lock); + if (list_empty(&csdev->feat_list)) { + spin_unlock(&csdev->cfg_lock); + return 0; + } + + list_for_each_entry(feat, &csdev->feat_list, node) { + dev_dbg(&csdev->dev, "Found feature:%s", feat->desc->name); + + if (feat->ops.set_on_enable) { + err = feat->ops.set_on_enable(feat, false); + dev_dbg(&csdev->dev, "Feature %s: %s", + feat->desc->name, err ? "Set failed" : "OK"); + if (!err) + break; + } + } + spin_unlock(&csdev->cfg_lock); + return err; +} +EXPORT_SYMBOL_GPL(cscfg_csdev_set_enabled_feats); + +void cscfg_csdev_save_enabled_feats(struct coresight_device *csdev) +{ + struct cscfg_feature_csdev *feat; + + spin_lock(&csdev->cfg_lock); + if (list_empty(&csdev->feat_list)) { + spin_unlock(&csdev->cfg_lock); + return; + } + + list_for_each_entry(feat, &csdev->feat_list, node) { + if (feat->ops.save_on_disable) + feat->ops.save_on_disable(feat, false); + } + spin_unlock(&csdev->cfg_lock); +} +EXPORT_SYMBOL_GPL(cscfg_csdev_save_enabled_feats); + +void cscfg_csdev_reset_feats(struct coresight_device *csdev) +{ + struct cscfg_feature_csdev *feat; + + spin_lock(&csdev->cfg_lock); + if (list_empty(&csdev->feat_list)) { + spin_unlock(&csdev->cfg_lock); + return; + } + + list_for_each_entry(feat, &csdev->feat_list, node) { + if (feat->ops.reset) + feat->ops.reset(feat); + } + spin_unlock(&csdev->cfg_lock); +} +EXPORT_SYMBOL_GPL(cscfg_csdev_reset_feats); + +static int cscfg_update_presets(struct cscfg_config_csdev *cfg, int preset) +{ + int i, j, line_offset = 0, val_idx = 0, max_idx; + u64 val; + struct cscfg_feature_csdev *feat; + struct cscfg_parameter_csdev *param; + const char *name; + + 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; + max_idx = cfg->desc->nr_total_params; + for (i = 0; i < cfg->nr_feat; i++) { + feat = cfg->feats[i]; + if (feat->nr_params) { + spin_lock(feat->csdev_spinlock); + 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; + } + spin_unlock(feat->csdev_spinlock); + } + + /* don't overrun the preset array line */ + if (val_idx >= max_idx) + break; + } + 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) +{ + int i, j; + struct cscfg_feature_csdev *feat; + struct cscfg_parameter_csdev *param; + const char *name; + u64 val; + + for (i = 0; i < cfg->nr_feat; i++) { + feat = cfg->feats[i]; + if (feat->nr_params) { + spin_lock(feat->csdev_spinlock); + 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); + } + } + spin_unlock(feat->csdev_spinlock); + } + } + return 0; +} + +static int cscfg_prog_config(struct cscfg_config_csdev *cfg, bool enable) +{ + int i, err = 0; + struct cscfg_feature_csdev *feat; + struct coresight_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) { + if (feat->ops.set_on_enable) + err = feat->ops.set_on_enable(feat, true); + } else { + if (feat->ops.save_on_disable) + feat->ops.save_on_disable(feat, true); + } + if (err) + break; + } + return err; +} + +/** + * Enable configuration for the device. + * Match the config id and optionally set preset values for parameters. + * + * @csdev: coresight device to set config on. + * @cfg_id: hash id of configuration. + * @preset: preset values to use - 0 for default. + */ +int cscfg_csdev_enable_config(struct coresight_device *csdev, + unsigned long cfg_id, + int preset) +{ + struct cscfg_config_csdev *cfg; + int err = 0; + + dev_dbg(&csdev->dev, "Check for config %lx, preset %d", cfg_id, preset); + + spin_lock(&csdev->cfg_lock); + list_for_each_entry(cfg, &csdev->syscfg_list, node) { + dev_dbg(&csdev->dev, "checking %s", cfg->desc->name); + if (cfg->id_hash == cfg_id) { + 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; + break; + } + } + spin_unlock(&csdev->cfg_lock); + return err; +} +EXPORT_SYMBOL_GPL(cscfg_csdev_enable_config); + +void cscfg_csdev_disable_config(struct coresight_device *csdev) +{ + struct cscfg_config_csdev *cfg; + + spin_lock(&csdev->cfg_lock); + list_for_each_entry(cfg, &csdev->syscfg_list, node) { + if (cfg->enabled) { + cscfg_prog_config(cfg, false); + cfg->enabled = false; + } + } + spin_unlock(&csdev->cfg_lock); +} +EXPORT_SYMBOL_GPL(cscfg_csdev_disable_config); diff --git a/drivers/hwtracing/coresight/coresight-config.h b/drivers/hwtracing/coresight/coresight-config.h index 8fd7ff991ced..a3d374ebb70f 100644 --- a/drivers/hwtracing/coresight/coresight-config.h +++ b/drivers/hwtracing/coresight/coresight-config.h @@ -287,4 +287,18 @@ struct cscfg_csdev_feat_ops { struct cscfg_feature_csdev *feat); }; +/* coresight config API functions */ + +/* helper functions for feature manipulation */ +void cscfg_set_def_ops(struct cscfg_feature_csdev *feat); + +/* enable / disable features or configs on a device */ +int cscfg_csdev_set_enabled_feats(struct coresight_device *csdev); +void cscfg_csdev_save_enabled_feats(struct coresight_device *csdev); +void cscfg_csdev_reset_feats(struct coresight_device *csdev); +int cscfg_csdev_enable_config(struct coresight_device *csdev, + unsigned long cfg_id, + int preset); +void cscfg_csdev_disable_config(struct coresight_device *csdev); + #endif /* _CORESIGHT_CORESIGHT_CONFIG_H */ diff --git a/drivers/hwtracing/coresight/coresight-syscfg.c b/drivers/hwtracing/coresight/coresight-syscfg.c index 53bc1d551171..98ee78e3412a 100644 --- a/drivers/hwtracing/coresight/coresight-syscfg.c +++ b/drivers/hwtracing/coresight/coresight-syscfg.c @@ -166,6 +166,7 @@ cscfg_alloc_csdev_feat(struct coresight_device *csdev, struct cscfg_feature_desc feat->csdev = csdev; for (i = 0; i < feat->nr_params; i++) feat->params[i].feat = feat; + cscfg_set_def_ops(feat); return feat; } @@ -195,6 +196,9 @@ static int cscfg_load_feat_csdev(struct coresight_device *csdev, list_add(&feat_csdev->node, &csdev->feat_list); spin_unlock(&csdev->cfg_lock); + /* force load of default parameter values into registers */ + feat_csdev->ops.reset(feat_csdev); + return 0; } From patchwork Fri Oct 30 17:56:50 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Leach X-Patchwork-Id: 11870447 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0C623C4741F for ; Fri, 30 Oct 2020 17:58:05 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 5872520724 for ; Fri, 30 Oct 2020 17:58:04 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="vIKOmIjz"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="b4ekQa26" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 5872520724 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:MIME-Version:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:References:In-Reply-To:Message-Id:Date:Subject:To: From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=pLuc/XtM9qATXexyUfrM2G5h4Lrpmp3xmDX4YwDwBU0=; b=vIKOmIjzTvbmEJhufIe0EFqxny X11vH6Fp0PGUi0JvZGfyx6YFzdvTUCDal+eS3V2RPfUCWUWPKOtJmoouKF2/kGFlZ06X+21vrYDlh nYMXQUZTDAM6RQdFPR4qdKcvJWnvEj0sV8P+ix/X7JIHTmEdiKGlTiaZVSfe+UU48hI9wUnyCFlX3 g7SmawqHjp21AmkBLKuppZ/XL/ZUsweOM7h2jUUygfBu0PawNc8SznJxOk3kqYuz2gAhDkAuHsCK3 OzJJ5vqgSZpzy1+1JZyLUSLDGCVyt+mzwcRd+A296acufTXQGPtFKXg0K3U3VPQZtxK2xMu0AmuBf atTFodaA==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kYYeV-0003qq-05; Fri, 30 Oct 2020 17:57:27 +0000 Received: from mail-wr1-x444.google.com ([2a00:1450:4864:20::444]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kYYe7-0003lT-M9 for linux-arm-kernel@lists.infradead.org; Fri, 30 Oct 2020 17:57:10 +0000 Received: by mail-wr1-x444.google.com with SMTP id w1so7426979wrm.4 for ; Fri, 30 Oct 2020 10:57:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=fnhKKm1kNyGRocxXWeA8x5GkuNBQ4iZFdMaD+sZUm08=; b=b4ekQa26168ms1s0PZDo6WIXR8wLU6LaCOdJ+1+/bsuNxb6x8QYwhtJyJURskwsNrK t+iD4TojwX03sulwXK7uferGHZTdfcp/D6MXygcyEpFRD/KVffKgDuL+akEUwcbdfi1C UbK0XHJjZ9KwNDy0pCdIp64q3FCqeyh4+72uo+ulG0jaLFcj9IPi98fQI8xTciwDsx8P N0dSu8mEVOaN8svd7fhwlcqS1BJAknQXue6+0FD0PMnfZs3waIz2ztj6QXJtTcRUyVgK WcLqeIUkiYacRJyrwjlUzr4S/i2DbjBCDQJuIS4ur4pb3hYwmPmO8JF9xngKu3vtsRFF DX4Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=fnhKKm1kNyGRocxXWeA8x5GkuNBQ4iZFdMaD+sZUm08=; b=ZVCWrOPVgQLZNf0gm9GvyKkJtaNIszIyFtgB72WCcneIjzt7WYO/rRB7789Mrna4li Ojflkk6yJwhRcMx7s1PJomvy/igBysNVLBAjloUinuww1RiRG1ZuXr8z3Zyt5XADF7cC 7lsIYzyOKXxNFYqG6FUXeiwjW2DV3xZc04Knb+c8TKUvrtopOrYx4qoBIMXMS6smmXv2 NqQ8JzwT0qv8/2YBqQ+oe27wLNFkj+XioL1iVcDj+/6ud4qTd2m9TEeYkY7SpL3/Mznz pVQgYJsjVh6uS1mpZhs4rd1Wcp8ztSCznyO+e+pr2oHaz2iJqS+jJhQEPhqus9SuHKw+ Ftfg== X-Gm-Message-State: AOAM530SAgPeyE7psPtbfo7QhQRnOiMxJmR/OhPHV6KmAXgx/4l8ta17 RaNLh1YBIphHjpq03fHyL5Kx/tffu1bBXg== X-Google-Smtp-Source: ABdhPJzIsc5buJ66Xp/38o6rd17yrUwyQ5gpd0AkmtWja4cnH1xYdXQ0ANwr0lFN0ECFYYeZCYf0jg== X-Received: by 2002:adf:9507:: with SMTP id 7mr4651947wrs.365.1604080622319; Fri, 30 Oct 2020 10:57:02 -0700 (PDT) Received: from linaro.org ([2a00:23c5:6801:1801:4964:83f8:d2e7:f2c9]) by smtp.gmail.com with ESMTPSA id o129sm5615563wmb.25.2020.10.30.10.57.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 30 Oct 2020 10:57:01 -0700 (PDT) From: Mike Leach To: linux-arm-kernel@lists.infradead.org, coresight@lists.linaro.org, mathieu.poirier@linaro.org Subject: [RFC PATCH v3 4/9] coresight: etm-perf: update to handle configuration selection Date: Fri, 30 Oct 2020 17:56:50 +0000 Message-Id: <20201030175655.30126-5-mike.leach@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201030175655.30126-1-mike.leach@linaro.org> References: <20201030175655.30126-1-mike.leach@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201030_135703_837096_18DCC554 X-CRM114-Status: GOOD ( 33.05 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: yabinc@google.com, Mike Leach , suzuki.poulose@arm.com MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org 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 --- .../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 | 23 ++- 4 files changed, 172 insertions(+), 28 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-config.h b/drivers/hwtracing/coresight/coresight-config.h index a3d374ebb70f..372f29a59688 100644 --- a/drivers/hwtracing/coresight/coresight-config.h +++ b/drivers/hwtracing/coresight/coresight-config.h @@ -154,7 +154,8 @@ struct cscfg_config_feat_ref { * @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. - * + * @id_ea: Extended attribute for perf configid value + * @event_ea: Extended attribute for perf event value */ struct cscfg_config_desc { const char *name; @@ -165,6 +166,8 @@ struct cscfg_config_desc { int nr_presets; int nr_total_params; const u64 *presets; /* nr_presets * nr_total_params */ + struct dev_ext_attribute *id_ea; + struct dev_ext_attribute *event_ea; }; /** diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c index a608081bd446..8a87984195ed 100644 --- a/drivers/hwtracing/coresight/coresight-etm-perf.c +++ b/drivers/hwtracing/coresight/coresight-etm-perf.c @@ -20,6 +20,8 @@ #include "coresight-etm-perf.h" #include "coresight-priv.h" +#include "coresight-config.h" +#include "coresight-syscfg.h" static struct pmu etm_pmu; static bool etm_perf_up; @@ -34,6 +36,11 @@ PMU_FORMAT_ATTR(timestamp, "config:" __stringify(ETM_OPT_TS)); PMU_FORMAT_ATTR(retstack, "config:" __stringify(ETM_OPT_RETSTK)); /* Sink ID - same for all ETMs */ PMU_FORMAT_ATTR(sinkid, "config2:0-31"); +/* preset - if sink ID is used as a configuration selector */ +PMU_FORMAT_ATTR(preset, "config:0-3"); +/* config ID - set if a system configuration is selected */ +PMU_FORMAT_ATTR(configid, "config2:32-63"); + static struct attribute *etm_config_formats_attr[] = { &format_attr_cycacc.attr, @@ -41,6 +48,8 @@ static struct attribute *etm_config_formats_attr[] = { &format_attr_timestamp.attr, &format_attr_retstack.attr, &format_attr_sinkid.attr, + &format_attr_preset.attr, + &format_attr_configid.attr, NULL, }; @@ -58,9 +67,29 @@ static const struct attribute_group etm_pmu_sinks_group = { .attrs = etm_config_sinks_attr, }; +static struct attribute *etm_config_cscfg_attr[] = { + NULL, +}; + +static const struct attribute_group etm_pmu_cscfg_group = { + .name = "configurations", + .attrs = etm_config_cscfg_attr, +}; + +static struct attribute *etm_config_events_attr[] = { + NULL, +}; + +static const struct attribute_group etm_pmu_events_group = { + .name = "events", + .attrs = etm_config_events_attr, +}; + static const struct attribute_group *etm_pmu_attr_groups[] = { &etm_pmu_format_group, &etm_pmu_sinks_group, + &etm_pmu_cscfg_group, + &etm_pmu_events_group, NULL, }; @@ -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); } @@ -537,21 +566,17 @@ static ssize_t etm_perf_sink_name_show(struct device *dev, return scnprintf(buf, PAGE_SIZE, "0x%lx\n", (unsigned long)(ea->var)); } -int etm_perf_add_symlink_sink(struct coresight_device *csdev) +int etm_perf_add_symlink_group(struct device *dev, + struct dev_ext_attribute **ext_attr, + const char *name, + const char *group_name) { - int ret; + struct dev_ext_attribute *ea; unsigned long hash; - const char *name; + int ret; struct device *pmu_dev = etm_pmu.dev; - struct device *dev = &csdev->dev; - struct dev_ext_attribute *ea; - if (csdev->type != CORESIGHT_DEV_TYPE_SINK && - csdev->type != CORESIGHT_DEV_TYPE_LINKSINK) - return -EINVAL; - - if (csdev->ea != NULL) - return -EINVAL; + *ext_attr = NULL; if (!etm_perf_up) return -EPROBE_DEFER; @@ -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; } -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=". + * 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"); + + if (!err) + err = etm_perf_add_cscfg_event(dev, cs_cfg); + + return err; +} + +void etm_perf_del_symlink_cscfg(struct cscfg_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 __init etm_perf_init(void) { int ret; diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.h b/drivers/hwtracing/coresight/coresight-etm-perf.h index 29d90dfeba31..3646a3837a0b 100644 --- a/drivers/hwtracing/coresight/coresight-etm-perf.h +++ b/drivers/hwtracing/coresight/coresight-etm-perf.h @@ -11,6 +11,7 @@ #include "coresight-priv.h" struct coresight_device; +struct cscfg_config_desc; /* * In both ETMv3 and v4 the maximum number of address comparator implentable @@ -69,6 +70,9 @@ static inline void *etm_perf_sink_config(struct perf_output_handle *handle) return data->snk_config; return NULL; } +int etm_perf_add_symlink_cscfg(struct device *dev, + struct cscfg_config_desc *cscfg_desc); +void etm_perf_del_symlink_cscfg(struct cscfg_config_desc *cscfg_desc); #else static inline int etm_perf_symlink(struct coresight_device *csdev, bool link) { return -EINVAL; } @@ -79,6 +83,10 @@ static inline void *etm_perf_sink_config(struct perf_output_handle *handle) { return NULL; } +int etm_perf_add_symlink_cscfg(struct device *dev, + struct cscfg_config_desc *cscfg_desc) +{ return -EINVAL; } +void etm_perf_del_symlink_cscfg(struct cscfg_config_desc *cscfg_desc) {} #endif /* CONFIG_CORESIGHT */ diff --git a/drivers/hwtracing/coresight/coresight-syscfg.c b/drivers/hwtracing/coresight/coresight-syscfg.c index 98ee78e3412a..8d52580daf04 100644 --- a/drivers/hwtracing/coresight/coresight-syscfg.c +++ b/drivers/hwtracing/coresight/coresight-syscfg.c @@ -7,6 +7,7 @@ #include #include "coresight-config.h" +#include "coresight-etm-perf.h" #include "coresight-syscfg.h" /* @@ -85,7 +86,7 @@ static int cscfg_add_csdev_cfg(struct coresight_device *csdev, struct cscfg_config_csdev *dev_cfg = NULL; struct cscfg_config_feat_ref *feat_ref; struct cscfg_feature_csdev *feat; - int checked; + int checked, err; /* look at each required feature and see if it matches any feature on the device */ for (checked = 0; checked < cfg_desc->nr_refs; checked++) { @@ -97,16 +98,22 @@ static int cscfg_add_csdev_cfg(struct coresight_device *csdev, 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->id_hash = (unsigned long)cfg_desc->id_ea->var; } dev_cfg->feats[dev_cfg->nr_feat++] = feat; } } + /* if matched features, add config to device.*/ - if (dev_cfg) + if (dev_cfg) { + /* add config name to perf event directory if this is valid source */ + if (match_info->match_flags & CS_CFG_MATCH_CLASS_SRC_ALL) + err = etm_perf_add_symlink_cscfg(&csdev->dev, cfg_desc); + if (err) + return err; list_add(&dev_cfg->node, &csdev->syscfg_list); + } return 0; } @@ -282,8 +289,9 @@ static int cscfg_load_config(struct cscfg_config_desc *cfg_desc) return err; list_add(&cfg_desc->item, &cscfg_data.config_list); + err = etm_perf_add_symlink_cscfg(to_device_cscfg(), cfg_desc); - return 0; + return err; } /* @@ -532,7 +540,12 @@ int cscfg_create_device(void) void cscfg_clear_device(void) { + struct cscfg_config_desc *cfg_desc; + mutex_lock(&cscfg_mutex); + list_for_each_entry(cfg_desc, &cscfg_data.config_list, item) { + etm_perf_del_symlink_cscfg(cfg_desc); + } device_unregister(to_device_cscfg()); mutex_unlock(&cscfg_mutex); } From patchwork Fri Oct 30 17:56:51 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Leach X-Patchwork-Id: 11870463 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 64552C4741F for ; Fri, 30 Oct 2020 18:00:18 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id B6AEF20A8B for ; Fri, 30 Oct 2020 18:00:17 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="P+1OPpb/"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="EsaaZkNE" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org B6AEF20A8B Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:MIME-Version:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:References:In-Reply-To:Message-Id:Date:Subject:To: From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=Rv+uGuPixHRXExYI4Z7pH3ifuIzQ1AORdSHD0OlmO00=; b=P+1OPpb/TOj1rkfqg781VKwW16 A9W9cJyQzjOmhvZ6eHHE83lOQ47h9ZIHZCzOVqiJePk5A5clxcdYeJYWBlOi3pwGJWbRERoNpjk2t L4J/W42hYFvD27cdoEF5TcHs5Fh7ELnpxKUlF4SFNasD0SxjWYBaRbp+jwWkwn6B7CI/RPMdML9IO S1WrldR4aDDT4XYXUIteVgQ/Ey0wCZD0mbjf+PHKMN+oeBSRANIyRAXphioRRKN7NdeZVDh0vKrVK Md2qY/z1VvSEHObqu2tcWRtICSvPGP1mrHArcfSsavhGF8aZqvXO0pfLQtZjoPPrqNG6Fq5PV7q6y AqG71BPg==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kYYfY-0004EH-PZ; Fri, 30 Oct 2020 17:58:32 +0000 Received: from mail-wr1-x444.google.com ([2a00:1450:4864:20::444]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kYYe8-0003lo-K4 for linux-arm-kernel@lists.infradead.org; Fri, 30 Oct 2020 17:57:15 +0000 Received: by mail-wr1-x444.google.com with SMTP id y12so7412496wrp.6 for ; Fri, 30 Oct 2020 10:57:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=lCplAYIG6UwI9kSkagYHVQyebLL+9kIN1QNDzRqbk/M=; b=EsaaZkNEf43l2AmLlNzWQ6L6oMuatahr/Li1gJYPwZsddhoGYwX2vc6KvPCh4xb6Sn BSEIoIWEyKyF2I9JdFFBxB/q5fNWz7dXTAVSyQIaMXq/Lnvmua1q9ZVAdlhVFfRg8r/I JiJKYDUsUQlBU81T1UpQxn3k+lx5m9F0X6ksZP+tX1Sa5nMoA6t5Ps9N+wwZ8Ou2Sz91 jnmQo5WSzqQVkTrtxsciNEsGb6TB3zs8JG+sQS9BPUjjhh56NkFWH3KwgpnCTB6xYxkK wBsTeHocN3gGlGNdkzOb4nbF/dBrpoWucfNJOWtm4tO6uEczeucHq6A0MAjm5TIoBdWj F3tQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=lCplAYIG6UwI9kSkagYHVQyebLL+9kIN1QNDzRqbk/M=; b=cKc1EcMsRxYvvXSZadsVJbtDbuVMYhBeKKqU0p1F2D8fSbB4iBfroTh7E2fyUqAHEu DmCHTHP7ux4nJM9qFR1oElV0TSY14E0gV1OhFqhYt6KL1k2W/+bqzATicbda33QY8xBj 8w5aF6mJ/VqA8scmyBzv4Yb91tRWWDdh4uZJpMAguR0neelf+0OKkNa9el48/HvTAcIE EgK5o/oUyRfEq0hnAXcdR9rXuvllo16EBGPGVFMEdThmJ1WUSPrqxNK92lg4Vd0b7PX+ NrQQc0ZepxmcMzMDcYJQKIIsZYMrSNM2p2GM21mzF4oLLuNQhpUmt7wuRklrBDfA/7gN vBOQ== X-Gm-Message-State: AOAM531+HZYOGObAUlN4u3SHdgdIz9HWQcolx2AwM0tGtgL+TBU8hVQr 7sUIJ7M7m03uAOEB15ovOHOKB5CohTTd2Q== X-Google-Smtp-Source: ABdhPJxBOiqMEdsSQjtNhFdDaLDnPh7CxTDBc1Omj4b9kdbEPmD8s9XaNS2FuLfdWcuXD+q3Ysfweg== X-Received: by 2002:a5d:66c9:: with SMTP id k9mr5109070wrw.158.1604080623330; Fri, 30 Oct 2020 10:57:03 -0700 (PDT) Received: from linaro.org ([2a00:23c5:6801:1801:4964:83f8:d2e7:f2c9]) by smtp.gmail.com with ESMTPSA id o129sm5615563wmb.25.2020.10.30.10.57.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 30 Oct 2020 10:57:02 -0700 (PDT) From: Mike Leach To: linux-arm-kernel@lists.infradead.org, coresight@lists.linaro.org, mathieu.poirier@linaro.org Subject: [RFC PATCH v3 5/9] coresight: etm4x: Add complex configuration handlers to etmv4 Date: Fri, 30 Oct 2020 17:56:51 +0000 Message-Id: <20201030175655.30126-6-mike.leach@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201030175655.30126-1-mike.leach@linaro.org> References: <20201030175655.30126-1-mike.leach@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201030_135704_841644_0C550707 X-CRM114-Status: GOOD ( 37.38 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: yabinc@google.com, Mike Leach , suzuki.poulose@arm.com MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org 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 --- drivers/hwtracing/coresight/Makefile | 3 +- .../hwtracing/coresight/coresight-etm4x-cfg.c | 181 ++++++++++++++++++ .../hwtracing/coresight/coresight-etm4x-cfg.h | 29 +++ .../coresight/coresight-etm4x-core.c | 36 +++- .../coresight/coresight-etm4x-sysfs.c | 3 + 5 files changed, 249 insertions(+), 3 deletions(-) create mode 100644 drivers/hwtracing/coresight/coresight-etm4x-cfg.c create mode 100644 drivers/hwtracing/coresight/coresight-etm4x-cfg.h diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile index daad9f103a78..ea544206204d 100644 --- a/drivers/hwtracing/coresight/Makefile +++ b/drivers/hwtracing/coresight/Makefile @@ -16,7 +16,8 @@ obj-$(CONFIG_CORESIGHT_SOURCE_ETM3X) += coresight-etm3x.o coresight-etm3x-y := coresight-etm3x-core.o coresight-etm-cp14.o \ coresight-etm3x-sysfs.o obj-$(CONFIG_CORESIGHT_SOURCE_ETM4X) += coresight-etm4x.o -coresight-etm4x-y := coresight-etm4x-core.o coresight-etm4x-sysfs.o +coresight-etm4x-y := coresight-etm4x-core.o coresight-etm4x-sysfs.o \ + coresight-etm4x-cfg.o obj-$(CONFIG_CORESIGHT_STM) += coresight-stm.o obj-$(CONFIG_CORESIGHT_CPU_DEBUG) += coresight-cpu-debug.o obj-$(CONFIG_CORESIGHT_CATU) += coresight-catu.o diff --git a/drivers/hwtracing/coresight/coresight-etm4x-cfg.c b/drivers/hwtracing/coresight/coresight-etm4x-cfg.c new file mode 100644 index 000000000000..9589d43e7947 --- /dev/null +++ b/drivers/hwtracing/coresight/coresight-etm4x-cfg.c @@ -0,0 +1,181 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright(C) 2020 Linaro Limited. All rights reserved. + * Author: Mike Leach + */ + +#include "coresight-etm4x.h" +#include "coresight-etm4x-cfg.h" +#include "coresight-priv.h" +#include "coresight-syscfg.h" + +/** + * etm4_cfg_map_reg_offset - validate and map the register offset into a + * location in the driver config struct. + * + * Limits the number of registers that can be accessed and programmed in + * features, to those which are used to control the trace capture parameters. + * + * Omits or limits access to those which the driver must use exclusively. + * + * Invalid offsets will result in fail code return and feature load failure. + * + * @drvdata: driver data to map into. + * @reg: register to map. + * @offset: device offset for the register + */ +static int etm4_cfg_map_reg_offset(struct etmv4_drvdata *drvdata, + struct cscfg_reg_csdev *reg, u32 offset) +{ + int err = -EINVAL, idx; + struct etmv4_config *drvcfg = &drvdata->config; + u32 off_mask; + +#define CHECKREG(cval, elem) \ + { \ + if (offset == cval) { \ + reg->drv_store = &drvcfg->elem; \ + err = 0; \ + break; \ + } \ + } + +#define CHECKREGIDX(cval, elem, off_idx) \ + { \ + if (off_mask == cval) { \ + reg->drv_store = &drvcfg->elem[off_idx]; \ + err = 0; \ + break; \ + } \ + } + + if (((offset >= TRCEVENTCTL0R) && (offset <= TRCVIPCSSCTLR)) || + ((offset >= TRCSEQRSTEVR) && (offset <= TRCEXTINSELR)) || + ((offset >= TRCCIDCCTLR0) && (offset <= TRCVMIDCCTLR1))) { + do { + CHECKREG(TRCEVENTCTL0R, eventctrl0); + CHECKREG(TRCEVENTCTL1R, eventctrl1); + CHECKREG(TRCSTALLCTLR, stall_ctrl); + CHECKREG(TRCTSCTLR, ts_ctrl); + CHECKREG(TRCSYNCPR, syncfreq); + CHECKREG(TRCCCCTLR, ccctlr); + CHECKREG(TRCBBCTLR, bb_ctrl); + CHECKREG(TRCVICTLR, vinst_ctrl); + CHECKREG(TRCVIIECTLR, viiectlr); + CHECKREG(TRCVISSCTLR, vissctlr); + CHECKREG(TRCVIPCSSCTLR, vipcssctlr); + CHECKREG(TRCSEQRSTEVR, seq_rst); + CHECKREG(TRCSEQSTR, seq_state); + CHECKREG(TRCEXTINSELR, ext_inp); + CHECKREG(TRCCIDCCTLR0, ctxid_mask0); + CHECKREG(TRCCIDCCTLR1, ctxid_mask1); + CHECKREG(TRCVMIDCCTLR0, vmid_mask0); + CHECKREG(TRCVMIDCCTLR1, vmid_mask1); + } while (0); + } else if ((offset & GENMASK(11, 4)) == TRCSEQEVRn(0)) { + /* sequencer state control registers */ + idx = (offset & GENMASK(3, 0)) / 4; + if (idx < ETM_MAX_SEQ_STATES) { + reg->drv_store = &drvcfg->seq_ctrl[idx]; + err = 0; + } + } else if ((offset >= TRCSSCCRn(0)) && (offset <= TRCSSPCICRn(7))) { + /* 32 bit, 8 off indexed register sets */ + idx = (offset & GENMASK(4, 0)) / 4; + off_mask = (offset & GENMASK(11, 5)); + do { + CHECKREGIDX(TRCSSCCRn(0), ss_ctrl, idx); + CHECKREGIDX(TRCSSCSRn(0), ss_status, idx); + CHECKREGIDX(TRCSSPCICRn(0), ss_pe_cmp, idx); + } while (0); + } else if ((offset >= TRCCIDCVRn(0)) && (offset <= TRCVMIDCVRn(7))) { + /* 64 bit, 8 off indexed register sets */ + idx = (offset & GENMASK(5, 0)) / 8; + off_mask = (offset & GENMASK(11, 6)); + do { + CHECKREGIDX(TRCCIDCVRn(0), ctxid_pid, idx); + CHECKREGIDX(TRCVMIDCVRn(0), vmid_val, idx); + } while (0); + } else if ((offset >= TRCRSCTLRn(2)) && + (offset <= TRCRSCTLRn((ETM_MAX_RES_SEL - 1)))) { + /* 32 bit resource selection regs, 32 off, skip fixed 0,1 */ + idx = (offset & GENMASK(6, 0)) / 4; + if (idx < ETM_MAX_RES_SEL) { + reg->drv_store = &drvcfg->res_ctrl[idx]; + err = 0; + } + } else if ((offset >= TRCACVRn(0)) && + (offset <= TRCACATRn((ETM_MAX_SINGLE_ADDR_CMP - 1)))) { + /* 64 bit addr cmp regs, 16 off */ + idx = (offset & GENMASK(6, 0)) / 8; + off_mask = offset & GENMASK(11, 7); + do { + CHECKREGIDX(TRCACVRn(0), addr_val, idx); + CHECKREGIDX(TRCACATRn(0), addr_acc, idx); + } 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); + CHECKREGIDX(TRCCNTCTLRn(0), cntr_ctrl, idx); + CHECKREGIDX(TRCCNTVRn(0), cntr_val, idx); + } 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 */ + feat->csdev_spinlock = &drvdata->spinlock; + + /* process the register descriptions */ + for (i = 0; i < feat->nr_regs && !err; i++) { + offset = feat_desc->regs[i].flags & CS_CFG_REG_ID_MASK; + 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_cs_cfg_register(struct coresight_device *csdev, const char *dev_name) +{ + struct cscfg_match_info cfg_info; + struct cscfg_csdev_feat_ops ops; + + cfg_info.dev_name = dev_name; + cfg_info.match_flags = CS_CFG_ETM4_MATCH_FLAGS; + + ops.load_feat = &etm4_cfg_load_feature; + + return cscfg_register_csdev(csdev, &cfg_info, &ops); +} diff --git a/drivers/hwtracing/coresight/coresight-etm4x-cfg.h b/drivers/hwtracing/coresight/coresight-etm4x-cfg.h new file mode 100644 index 000000000000..bf33c720b5e9 --- /dev/null +++ b/drivers/hwtracing/coresight/coresight-etm4x-cfg.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. + */ + +#ifndef _CORESIGHT_CORESIGHT_ETM4X_CFG_H +#define _CORESIGHT_CORESIGHT_ETM4X_CFG_H + +#include "coresight-config.h" +#include "coresight-etm4x.h" + +/* ETMv4 specific config defines */ + +/* resource IDs */ + +#define ETM4_CFG_RES_CTR 0x00001000 +#define ETM4_CFG_RES_CMP 0x00002000 +#define ETM4_CFG_RES_CMP_PAIR0 0x00003000 +#define ETM4_CFG_RES_CMP_PAIR1 0x00004000 +#define ETM4_CFG_RES_SEL 0x00005000 +#define ETM4_CFG_RES_SEL_PAIR0 0x00006000 +#define ETM4_CFG_RES_SEL_PAIR1 0x00007000 +#define ETM4_CFG_RES_SEQ 0x00008000 +#define ETM4_CFG_RES_TS 0x00009000 +#define ETM4_CFG_RES_MASK 0x0000F000 + +int etm4_cs_cfg_register(struct coresight_device *csdev, const char *dev_name); + +#endif /* _CORESIGHT_CORESIGHT_ETM4X_CFG_H */ diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c index 6096d7abf80d..88213aa7a72e 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c @@ -34,6 +34,8 @@ #include "coresight-etm4x.h" #include "coresight-etm-perf.h" +#include "coresight-etm4x-cfg.h" +#include "coresight-syscfg.h" static int boot_enable; module_param(boot_enable, int, 0444); @@ -321,12 +323,15 @@ static int etm4_config_timestamp_event(struct etmv4_drvdata *drvdata) return ret; } -static int etm4_parse_event_config(struct etmv4_drvdata *drvdata, +static int etm4_parse_event_config(struct coresight_device *csdev, struct perf_event *event) { int ret = 0; + struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); struct etmv4_config *config = &drvdata->config; struct perf_event_attr *attr = &event->attr; + unsigned long cfg_id; + int preset; if (!attr) { ret = -EINVAL; @@ -384,6 +389,19 @@ 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. + */ + if (attr->config2 & GENMASK_ULL(63, 32)) { + cfg_id = (u32)(attr->config2 >> 32); + preset = attr->config & 0xF; + ret = cscfg_csdev_enable_config(csdev, cfg_id, preset); + } + out: return ret; } @@ -400,7 +418,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 */ @@ -416,6 +434,8 @@ static int etm4_enable_sysfs(struct coresight_device *csdev) struct etm4_enable_arg arg = { }; int ret; + cscfg_csdev_set_enabled_feats(csdev); + spin_lock(&drvdata->spinlock); /* @@ -530,11 +550,14 @@ 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); + if (attr->config2 & GENMASK_ULL(63, 32)) + cscfg_csdev_disable_config(csdev); /* * Check if the start/stop logic was active when the unit was stopped. @@ -569,6 +592,7 @@ static void etm4_disable_sysfs(struct coresight_device *csdev) smp_call_function_single(drvdata->cpu, etm4_disable_hw, drvdata, 1); spin_unlock(&drvdata->spinlock); + cscfg_csdev_save_enabled_feats(csdev); cpus_read_unlock(); dev_dbg(&csdev->dev, "ETM tracing disabled\n"); @@ -1536,6 +1560,13 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id) return ret; } + /* register with config infrastructure & load any current features */ + ret = etm4_cs_cfg_register(drvdata->csdev, dev_name(dev)); + if (ret) { + coresight_unregister(drvdata->csdev); + return ret; + } + etmdrvdata[drvdata->cpu] = drvdata; pm_runtime_put(&adev->dev); @@ -1588,6 +1619,7 @@ static int __exit etm4_remove(struct amba_device *adev) cpus_read_unlock(); + cscfg_unregister_csdev(drvdata->csdev); coresight_unregister(drvdata->csdev); return 0; diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c index 989ce7b8ade7..78e68f3032d5 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c @@ -9,6 +9,7 @@ #include #include "coresight-etm4x.h" #include "coresight-priv.h" +#include "coresight-config.h" static int etm4_set_mode_exclude(struct etmv4_drvdata *drvdata, bool exclude) { @@ -269,6 +270,8 @@ static ssize_t reset_store(struct device *dev, spin_unlock(&drvdata->spinlock); + cscfg_csdev_reset_feats(to_coresight_device(dev)); + return size; } static DEVICE_ATTR_WO(reset); From patchwork Fri Oct 30 17:56:52 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Leach X-Patchwork-Id: 11870449 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D7F46C00A89 for ; Fri, 30 Oct 2020 17:58:46 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 4D99620724 for ; Fri, 30 Oct 2020 17:58:46 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="CfSGScQy"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="yiPtjc70" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 4D99620724 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:MIME-Version:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:References:In-Reply-To:Message-Id:Date:Subject:To: From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=Z0JLae5v1Ha8VLN7GrA+pc7LUBR+JWs42HxkmyEbzkk=; b=CfSGScQy6D3JIG42Wswsc5OsiV fFPB8BR5H5haAEgnfezdrF5QznVv28Ob7KBaYvVnBdDS/Ig1lndOGpuNdoiEy+ifEyQyQizunhGlD mSbBrGL37IRBW+yhKlkNQUn//OHuDR3ByPNR0BTa+QvY2EMBdeRCy6sFM2leR5HN6day8qaTxSBaS dviOdQHYhEKnrThut9PKJTZ0+ncnRDhdM6XzOxsfvDlwHYcWVAWSBsfV1cmwulxTPTwUD10rlCyhF /CuwWQTl3vd6CIkdK++yW4+xFyUpyAcwiCrB3GjrzwpAjaN4NULMnZ9WhddLeCBf8qFosPwpAnKeS dQv27s0w==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kYYf4-000420-M1; Fri, 30 Oct 2020 17:58:02 +0000 Received: from mail-wr1-x443.google.com ([2a00:1450:4864:20::443]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kYYe9-0003m8-KB for linux-arm-kernel@lists.infradead.org; Fri, 30 Oct 2020 17:57:14 +0000 Received: by mail-wr1-x443.google.com with SMTP id n15so7441457wrq.2 for ; Fri, 30 Oct 2020 10:57:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=yYqsuyi7DaOO7uWNEXcL2jXvZXiIWT42P3sP82JQVt4=; b=yiPtjc70iMviCFZN2uJQt2DtGp/UcNDfl7ExeHo9D6EBb/u8a5M9h+qqKzMNeEGmP7 CEqyZzk+FpvzdH1Vbed2kcjgjZmrMZDAACV67WA/S+vsV740sd3MmlAbya5vG9YP+cBT HWbZsnxEw4bkLYT7EdnGwgf/v6rDFTAIIW1Na9IMcGtgQWPCCFiEJ9Nr6HRSxh5ZrgbH fnFUn0IMw3ZEYlRY06Nkse4MEFHazlwKLua2pGLqR3Te27UrMGk6752OEjW1ooScmdMr x/GQTpml9XV18+CRibzFI7SWQYGk4IpzCpU1eU3Y26LcrvBgViQtvhDOvYJRlDRggPa0 yQNw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=yYqsuyi7DaOO7uWNEXcL2jXvZXiIWT42P3sP82JQVt4=; b=fAFs7y9vk+g7hzDLi/dXLKrJcFRzyHqafVMz8/xa+IRKPLg4jGyVIbN5yiUU7OiOCE WuodLj6PmhdKw84/0ybE44H0bDZHgDd72PGJPw9G9/+cGZBn+/hYGrDDHEH5DcxBYWP2 2rBBp0OqmQNJprt4m61XeCZXs/cxcK/LTAVvi9p/wZWqwl7K4UlNFR/+8XsMoAVASygg yQcXh31U+VnW1z+Z+v5Xg27Lhc1EC5BQEUoHxN0VbLzLJVSCb1i51gl2mcRfOHf5YtZ5 i6UgQGGxJtq3uBr0GJ9l2FYPPmLHqSpgtbAA4VRk+rR7oRsQZJDUYTycGsEeT5tzrIrJ i1xQ== X-Gm-Message-State: AOAM5303sUpdXOjFYxcalJLdmZbvGyWYxrI319KsgIOIeiHjedLR9vEx bHCK7/4J8PJ7RloniF6V2fH06Z25A/+apQ== X-Google-Smtp-Source: ABdhPJx8ritAG5pI3o4C+XM4YqGlQ4/b8tGGbRvuKkb1pJSoGyoVboh4o7W6tJXBUhAxvSdlwun2dQ== X-Received: by 2002:adf:ce91:: with SMTP id r17mr4862580wrn.326.1604080624372; Fri, 30 Oct 2020 10:57:04 -0700 (PDT) Received: from linaro.org ([2a00:23c5:6801:1801:4964:83f8:d2e7:f2c9]) by smtp.gmail.com with ESMTPSA id o129sm5615563wmb.25.2020.10.30.10.57.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 30 Oct 2020 10:57:03 -0700 (PDT) From: Mike Leach To: linux-arm-kernel@lists.infradead.org, coresight@lists.linaro.org, mathieu.poirier@linaro.org Subject: [RFC PATCH v3 6/9] coresight: config: Add preloaded configurations Date: Fri, 30 Oct 2020 17:56:52 +0000 Message-Id: <20201030175655.30126-7-mike.leach@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201030175655.30126-1-mike.leach@linaro.org> References: <20201030175655.30126-1-mike.leach@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201030_135705_761048_2EBF3CDD X-CRM114-Status: GOOD ( 24.05 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: yabinc@google.com, Mike Leach , suzuki.poulose@arm.com MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org 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 --- drivers/hwtracing/coresight/Makefile | 3 +- .../coresight/coresight-cfg-preload.c | 160 ++++++++++++++++++ drivers/hwtracing/coresight/coresight-core.c | 6 + .../hwtracing/coresight/coresight-syscfg.h | 1 + 4 files changed, 169 insertions(+), 1 deletion(-) create mode 100644 drivers/hwtracing/coresight/coresight-cfg-preload.c diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile index ea544206204d..9de5586cfd1a 100644 --- a/drivers/hwtracing/coresight/Makefile +++ b/drivers/hwtracing/coresight/Makefile @@ -4,7 +4,8 @@ # obj-$(CONFIG_CORESIGHT) += coresight.o coresight-y := coresight-core.o coresight-etm-perf.o coresight-platform.o \ - coresight-sysfs.o coresight-syscfg.o coresight-config.o + coresight-sysfs.o coresight-syscfg.o coresight-config.o \ + coresight-cfg-preload.o obj-$(CONFIG_CORESIGHT_LINK_AND_SINK_TMC) += coresight-tmc.o coresight-tmc-y := coresight-tmc-core.o coresight-tmc-etf.o \ coresight-tmc-etr.o diff --git a/drivers/hwtracing/coresight/coresight-cfg-preload.c b/drivers/hwtracing/coresight/coresight-cfg-preload.c new file mode 100644 index 000000000000..0975d64a1d9e --- /dev/null +++ b/drivers/hwtracing/coresight/coresight-cfg-preload.c @@ -0,0 +1,160 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright(C) 2020 Linaro Limited. All rights reserved. + * Author: Mike Leach + */ + +#include "coresight-config.h" +#include "coresight-syscfg.h" +#include "coresight-etm4x-cfg.h" + +/* preload configurations and features */ + +/* preload in features for ETMv4 */ + +/* strobe feature */ + +/* register defines */ +#define STRB_REG_CTR (CS_CFG_REG_RESOURCE | ETM4_CFG_RES_CTR) +#define STRB_REG_CTR_RB (STRB_REG_CTR | CS_CFG_REG_VAL_SAVE) +#define STRB_REG_CTR_PRM (STRB_REG_CTR | CS_CFG_REG_VAL_PARAM) +#define STRB_REG_SEQ (CS_CFG_REG_RESOURCE | ETM4_CFG_RES_SEQ) +#define STRB_REG_SEL (CS_CFG_REG_RESOURCE | ETM4_CFG_RES_SEL) +#define STRB_REG_VI (CS_CFG_REG_STD | CS_CFG_REG_VAL_MASK) + +static struct cscfg_parameter_desc strobe_params[] = { + { + .name = "window", + .value = 5000, + }, + { + .name = "period", + .value = 10000, + }, +}; + +static struct cscfg_regval strobe_regs[] = { + /* resource selectors */ + { + .flags = STRB_REG_SEL | TRCRSCTLRn(2), + .val32 = 0x20001, + }, + { + .flags = STRB_REG_SEQ | TRCRSCTLRn(3), + .val32 = 0x20002, + }, + /* strobe window counter 0 - reload from param 0 */ + { + .flags = STRB_REG_CTR_RB | TRCCNTVRn(0), + }, + { + .flags = STRB_REG_CTR_PRM | TRCCNTRLDVRn(0), + .val32 = 0, + }, + { + .flags = STRB_REG_CTR | TRCCNTCTLRn(0), + .val32 = 0x10001, + }, + /* strobe period counter 1 - reload from param 1 */ + { + .flags = STRB_REG_CTR_RB | TRCCNTVRn(1), + }, + { + .flags = STRB_REG_CTR_PRM | TRCCNTRLDVRn(1), + .val32 = 1, + }, + { + .flags = STRB_REG_CTR | TRCCNTCTLRn(1), + .val32 = 0x8102, + }, + /* sequencer */ + { + .flags = STRB_REG_SEQ | TRCSEQEVRn(0), + .val32 = 0x0081, + }, + { + .flags = STRB_REG_SEQ | TRCSEQEVRn(1), + .val32 = 0x0000, + }, + /* view-inst */ + { + .flags = STRB_REG_VI | TRCVICTLR, + .val32 = 0x0003, + .mask32 = 0x0003, + }, + /* end of regs */ +}; + +static struct cscfg_feature_desc strobe = { + .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, +}; + +static struct cscfg_feature_desc *preload_feats[] = { + &strobe, + 0 +}; + +/* 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) + +static struct cscfg_config_feat_ref afdo_refs[] = { + { + .name = "strobing", + .nr_params = ARRAY_SIZE(strobe_params), + .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 }, +}; + +static 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", + .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], +}; + +static struct cscfg_config_desc *preload_cfgs[] = { + &afdo, + 0 +}; + +/* preload called with mutex locked */ +int cscfg_preload(void) +{ + return cscfg_load_config_sets(preload_cfgs, preload_feats); +} diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c index 481d2b7b6b6f..dca84b3f5fca 100644 --- a/drivers/hwtracing/coresight/coresight-core.c +++ b/drivers/hwtracing/coresight/coresight-core.c @@ -1680,9 +1680,15 @@ static int __init coresight_init(void) /* initialise the coresight syscfg API */ ret = cscfg_init(); + if (ret) + goto exit_perf_close; + + /* preload builtin configurations */ + ret = cscfg_preload(); if (!ret) return 0; +exit_perf_close: etm_perf_exit(); exit_bus_unregister: bus_unregister(&coresight_bustype); diff --git a/drivers/hwtracing/coresight/coresight-syscfg.h b/drivers/hwtracing/coresight/coresight-syscfg.h index ecf4aac7d712..e8f352599dd7 100644 --- a/drivers/hwtracing/coresight/coresight-syscfg.h +++ b/drivers/hwtracing/coresight/coresight-syscfg.h @@ -45,6 +45,7 @@ struct cscfg_csdev_register { /* internal core operations for cscfg */ int __init cscfg_init(void); void __exit cscfg_exit(void); +int cscfg_preload(void); /* syscfg external API */ int cscfg_load_config_sets(struct cscfg_config_desc **cfg_descs, From patchwork Fri Oct 30 17:56:53 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Leach X-Patchwork-Id: 11870465 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 86AD4C00A89 for ; Fri, 30 Oct 2020 18:00:41 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id E5C5320724 for ; Fri, 30 Oct 2020 18:00:40 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="16tLBYUQ"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="Lk+/Zufs" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org E5C5320724 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:MIME-Version:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:References:In-Reply-To:Message-Id:Date:Subject:To: From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=V2x9p+HIags7mhjeYBTGM3UKiojnTApSBQZzm+Sew00=; b=16tLBYUQxcyDdCA5Lbo8edG+Pa wrQyMWl0eDnnFyGRvTvQhLSCreKEqGTsGYB9Qu2OYJs90MOQJqFDCHZZZTod+5vCVFQKvvcfR7PQP IJ2fLoCtJpaXs3/ncJkTEbYZ8YHgrBqd60ttJiRX4Q2CeS/9WnK18+ydoQ2mdwKYHYfAEpRv7+y3L kupUd5yFKoOof6xmLIAkQhVD2YZt2JbIkW6mdkRon2lLWmUY+09+8bG9GQkIxO38/SeEH4ij30By6 q7AmML3WmZNMTSwro1k5C5d+Sx8TT3KEixd9uYlY/fYGTlWTvDisR9/fHF1MWIyY87vEg7xIW2R57 Li7GLlMg==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kYYfv-0004Ot-7r; Fri, 30 Oct 2020 17:58:55 +0000 Received: from mail-wm1-x344.google.com ([2a00:1450:4864:20::344]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kYYeD-0003n2-Lq for linux-arm-kernel@lists.infradead.org; Fri, 30 Oct 2020 17:57:16 +0000 Received: by mail-wm1-x344.google.com with SMTP id e2so3733791wme.1 for ; Fri, 30 Oct 2020 10:57:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=CZQQJ5phXo5/JkEzOdlf4FZRfsVcLIuuSX5X69bT7OQ=; b=Lk+/ZufsYHdwa6JlLCDrUko6mqgzuMvjdHPqDKppNR5oMIsZieY0xKnCTewkhAOvG8 Z7OaQtA9tDPhRxmvEpbjwMM9tMbbVkOaPgDp4FHHvt7EHGxr6ilK9Rt1AU+O7sJVKN3s jXpl3PmfxmNRI+bSDHzxOdElw16DrmNz/chaoVq8HWZ7cJpe0vLRXfnEzZRtpGzakSNM /tbv5MNwl6UN91PzRSHFLnFd5bLDjE+MafYB2tXzmwNKuQ6V+MwDQDy40xZVBtlwfFdA fg9AjMO9YUFklddeKXr4wORU0lSN5fS043jFJCgEE9o8p+sh01/l6vOL2WWWkiz1NfBB kkJw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=CZQQJ5phXo5/JkEzOdlf4FZRfsVcLIuuSX5X69bT7OQ=; b=OSfNdDzVkFUSQauO7NoceC5T6220Po1T71kzLziDlZBilghIK5rc2Qqw9BeN44QOwG CZI6tiSjhK6keg2CNzH9tqZVEnIqGpTzPFNi4m2UJs2Y3xVJ8A3h2kpX2Ep8+sXPYA9Y wsDV38W8NWE+STOO/V1k4nGETQSJZBJgHDH6w+E/90HYf0ml+8CaJCztUo8+k8pM925z JPf2I8cuABqT2PosncwrQ4gqAWaTGMUZ3DAE96tF9lydY9BghoyRsQAElsB4RCQNIsIs xm0a7XIC2iPfjFWwAP2C++JgH+W3X7xFM7xJCcQDwLGwgGyHJNnC8qzcvpdes3DwZ4ff SXyQ== X-Gm-Message-State: AOAM530s6k0MK1kvs0QOnN4gnHutW5fbJcFAGiLf/MlABcv7SAWDNb4F psgETfMYL8Q/xW1CgXocW1r2a0OXphPK+A== X-Google-Smtp-Source: ABdhPJxXFKO8MGJuCu0ON+0Fd4rQQLf0UQfDb/3PiKcFV/krtIpOCVOTzwWs0UN5U1ioqyPY4dXGrw== X-Received: by 2002:a7b:cb8c:: with SMTP id m12mr4246219wmi.12.1604080625375; Fri, 30 Oct 2020 10:57:05 -0700 (PDT) Received: from linaro.org ([2a00:23c5:6801:1801:4964:83f8:d2e7:f2c9]) by smtp.gmail.com with ESMTPSA id o129sm5615563wmb.25.2020.10.30.10.57.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 30 Oct 2020 10:57:04 -0700 (PDT) From: Mike Leach To: linux-arm-kernel@lists.infradead.org, coresight@lists.linaro.org, mathieu.poirier@linaro.org Subject: [RFC PATCH v3 7/9] coresight: syscfg: Add initial configfs support. Date: Fri, 30 Oct 2020 17:56:53 +0000 Message-Id: <20201030175655.30126-8-mike.leach@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201030175655.30126-1-mike.leach@linaro.org> References: <20201030175655.30126-1-mike.leach@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201030_135709_912576_E1FDA5AA X-CRM114-Status: GOOD ( 28.21 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: yabinc@google.com, Mike Leach , suzuki.poulose@arm.com MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org 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 --- drivers/hwtracing/coresight/Makefile | 2 +- .../hwtracing/coresight/coresight-config.c | 2 + .../hwtracing/coresight/coresight-config.h | 5 +- .../coresight/coresight-syscfg-configfs.c | 418 ++++++++++++++++++ .../coresight/coresight-syscfg-configfs.h | 47 ++ .../hwtracing/coresight/coresight-syscfg.c | 31 ++ .../hwtracing/coresight/coresight-syscfg.h | 4 + 7 files changed, 507 insertions(+), 2 deletions(-) create mode 100644 drivers/hwtracing/coresight/coresight-syscfg-configfs.c create mode 100644 drivers/hwtracing/coresight/coresight-syscfg-configfs.h diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile index 9de5586cfd1a..4ec226c44f5b 100644 --- a/drivers/hwtracing/coresight/Makefile +++ b/drivers/hwtracing/coresight/Makefile @@ -5,7 +5,7 @@ obj-$(CONFIG_CORESIGHT) += coresight.o coresight-y := coresight-core.o coresight-etm-perf.o coresight-platform.o \ coresight-sysfs.o coresight-syscfg.o coresight-config.o \ - coresight-cfg-preload.o + coresight-cfg-preload.o coresight-syscfg-configfs.o obj-$(CONFIG_CORESIGHT_LINK_AND_SINK_TMC) += coresight-tmc.o coresight-tmc-y := coresight-tmc-core.o coresight-tmc-etf.o \ coresight-tmc-etr.o diff --git a/drivers/hwtracing/coresight/coresight-config.c b/drivers/hwtracing/coresight/coresight-config.c index d911e0f083c1..04e7cb4ff769 100644 --- a/drivers/hwtracing/coresight/coresight-config.c +++ b/drivers/hwtracing/coresight/coresight-config.c @@ -111,8 +111,10 @@ static void cscfg_reset_feat(struct cscfg_feature_csdev *feat) * set the default values for all parameters and regs from the * relevant static descriptors. */ + spin_lock(&feat->desc->param_lock); for (i = 0; i < feat->nr_params; i++) feat->params[i].current_value = feat->desc->params[i].value; + spin_unlock(&feat->desc->param_lock); for (i = 0; i < feat->nr_regs; i++) { reg_desc = &feat->desc->regs[i]; diff --git a/drivers/hwtracing/coresight/coresight-config.h b/drivers/hwtracing/coresight/coresight-config.h index 372f29a59688..39fcac011aa0 100644 --- a/drivers/hwtracing/coresight/coresight-config.h +++ b/drivers/hwtracing/coresight/coresight-config.h @@ -7,6 +7,7 @@ #ifndef _CORESIGHT_CORESIGHT_CONFIG_H #define _CORESIGHT_CORESIGHT_CONFIG_H +#include #include #include @@ -89,6 +90,7 @@ struct cscfg_regval { * @match_flags: matching information if loading into a device * @nr_params: number of parameters used. * @params: array of parameters used. + * @param_lock: protect params when accessing default values. * @nr_regs: number of registers used. * @reg: array of registers used. */ @@ -99,6 +101,7 @@ struct cscfg_feature_desc { u32 match_flags; int nr_params; struct cscfg_parameter_desc *params; + spinlock_t param_lock; int nr_regs; struct cscfg_regval *regs; }; @@ -239,7 +242,7 @@ struct cscfg_feat_ops { * @ops: standard ops to enable and disable features on devices. */ struct cscfg_feature_csdev { - const struct cscfg_feature_desc *desc; + struct cscfg_feature_desc *desc; struct coresight_device *csdev; struct list_head node; spinlock_t *csdev_spinlock; diff --git a/drivers/hwtracing/coresight/coresight-syscfg-configfs.c b/drivers/hwtracing/coresight/coresight-syscfg-configfs.c new file mode 100644 index 000000000000..ff7ea678100a --- /dev/null +++ b/drivers/hwtracing/coresight/coresight-syscfg-configfs.c @@ -0,0 +1,418 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 Linaro Limited, All rights reserved. + * Author: Mike Leach + */ + +#include + +#include "coresight-syscfg-configfs.h" + +/* + * configfs support for syscfg device. + * + * config fs is used to manage configurations and features on the + * coresight system. + */ + +static struct cscfg_device *cscfg_fs_get_cscfg_dev(void); + +static struct device *cscfg_dev_to_dev(void) +{ + return cscfg_fs_get_cscfg_dev() ? &cscfg_fs_get_cscfg_dev()->dev : NULL; +} + +/* + * Declare the subsystem - with base attributes allowing listing of + * loaded configurations + */ +static inline struct cscfg_fs_config *to_cscfg_fs_config_group(struct config_group *group) +{ + return container_of(group, struct cscfg_fs_config, group); +} + +/* configurations sub-group */ + +/* attributes for the config view group */ +static ssize_t cscfg_cfg_description_show(struct config_item *item, char *page) +{ + struct cscfg_fs_config *fs_config = to_cscfg_fs_config_group(to_config_group(item)); + + return scnprintf(page, PAGE_SIZE, "%s\n", fs_config->desc->brief); +} +CONFIGFS_ATTR_RO(cscfg_cfg_, description); + +static ssize_t cscfg_cfg_refs_show(struct config_item *item, char *page) +{ + struct cscfg_fs_config *fs_config = to_cscfg_fs_config_group(to_config_group(item)); + const struct cscfg_config_desc *desc = fs_config->desc; + ssize_t ch_used = 0; + int i; + + if (desc->nr_refs) { + ch_used += scnprintf(page, PAGE_SIZE, "references %d features:-\n", 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); + } + } else + ch_used = scnprintf(page, PAGE_SIZE, "no features referenced\n"); + return ch_used; +} +CONFIGFS_ATTR_RO(cscfg_cfg_, refs); + +static ssize_t cscfg_cfg_nr_presets_show(struct config_item *item, char *page) +{ + struct cscfg_fs_config *fs_config = to_cscfg_fs_config_group(to_config_group(item)); + + return scnprintf(page, PAGE_SIZE, "%d\n", fs_config->desc->nr_presets); +} +CONFIGFS_ATTR_RO(cscfg_cfg_, nr_presets); + +static ssize_t cscfg_cfg_preset_values_show(struct config_item *item, char *page) +{ + struct cscfg_fs_config *fs_config = to_cscfg_fs_config_group(to_config_group(item)); + const struct cscfg_config_desc *cfg = fs_config->desc; + const struct cscfg_feature_desc *feat; + ssize_t used = 0; + int i, j, val_idx, preset_idx; + + if (!fs_config->desc->nr_presets) + return scnprintf(page, PAGE_SIZE, "No presets defined\n"); + + used = scnprintf(page, PAGE_SIZE, "%d presets, %d parameters per preset\n", + fs_config->desc->nr_presets, cfg->nr_total_params); + + for (preset_idx = 0; preset_idx < fs_config->desc->nr_presets; preset_idx++) { + /* start index on the correct array line */ + val_idx = cfg->nr_total_params * preset_idx; + + /* preset indexes are used as 1 based by the user */ + used += scnprintf(page + used, PAGE_SIZE - used, "preset[%d]: ", preset_idx+1); + + /* + * A set of presets is the sum of all params in used features, + * in order of declaration of features and params in the features + */ + for (i = 0; i < cfg->nr_refs; i++) { + feat = cscfg_get_named_feat_desc(cfg->refs[i].name); + for (j = 0; j < cfg->refs[i].nr_params; j++) { + used += scnprintf(page + used, PAGE_SIZE - used, + "%s.%s = 0x%llx ", + cfg->refs[i].name, feat->params[j].name, + cfg->presets[val_idx++]); + } + } + used += scnprintf(page + used, PAGE_SIZE - used, "\n"); + } + return used; +} +CONFIGFS_ATTR_RO(cscfg_cfg_, preset_values); + +static struct configfs_attribute *cscfg_config_view_attrs[] = { + &cscfg_cfg_attr_description, + &cscfg_cfg_attr_refs, + &cscfg_cfg_attr_nr_presets, + &cscfg_cfg_attr_preset_values, + NULL, +}; + +static struct config_item_type cscfg_config_view_type = { + .ct_owner = THIS_MODULE, + .ct_attrs = cscfg_config_view_attrs, +}; + +static struct config_group *cscfg_create_config_group(struct cscfg_config_desc *cfg_desc) +{ + struct cscfg_fs_config *cfg_view; + struct device *dev = cscfg_dev_to_dev(); + + if (!dev) + return ERR_PTR(-EINVAL); + + cfg_view = devm_kzalloc(dev, sizeof(struct cscfg_fs_config), GFP_KERNEL); + if (!cfg_view) + return ERR_PTR(-ENOMEM); + + cfg_view->desc = cfg_desc; + config_group_init_type_name(&cfg_view->group, cfg_desc->name, &cscfg_config_view_type); + return &cfg_view->group; +} + +static struct config_item_type cscfg_configs_type = { + .ct_owner = THIS_MODULE, +}; + +static struct cscfg_fs_def_group cscfg_configs_grp = { + .group = { + .cg_item = { + .ci_namebuf = "configurations", + .ci_type = &cscfg_configs_type, + }, + }, +}; + + +/* attributes for features view */ + +static inline struct cscfg_fs_feature *to_cscfg_fs_feature_group(struct config_group *group) +{ + return container_of(group, struct cscfg_fs_feature, group); +} + +static ssize_t cscfg_feat_description_show(struct config_item *item, char *page) +{ + struct cscfg_fs_feature *fs_feat = to_cscfg_fs_feature_group(to_config_group(item)); + + return scnprintf(page, PAGE_SIZE, "%s\n", fs_feat->desc->brief); +} +CONFIGFS_ATTR_RO(cscfg_feat_, description); + +static ssize_t cscfg_feat_matches_show(struct config_item *item, char *page) +{ + struct cscfg_fs_feature *fs_feat = to_cscfg_fs_feature_group(to_config_group(item)); + u32 match_flags = fs_feat->desc->match_flags; + int used = 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 "); + + if (match_flags & CS_CFG_MATCH_CLASS_CTI_ALL) + used += scnprintf(page + used, PAGE_SIZE - used, "CTI_ALL "); + + if (match_flags & CS_CFG_MATCH_CLASS_CTI_CPU) + used += scnprintf(page + used, PAGE_SIZE - used, "CTI_CPU "); + + if (match_flags & CS_CFG_MATCH_CLASS_CTI_SYS) + used += scnprintf(page + used, PAGE_SIZE - used, "CTI_SYS "); + + used += scnprintf(page + used, PAGE_SIZE - used, "\n"); + return used; +} +CONFIGFS_ATTR_RO(cscfg_feat_, matches); + +static ssize_t cscfg_feat_nr_params_show(struct config_item *item, char *page) +{ + struct cscfg_fs_feature *fs_feat = to_cscfg_fs_feature_group(to_config_group(item)); + + return scnprintf(page, PAGE_SIZE, "%d\n", fs_feat->desc->nr_params); +} +CONFIGFS_ATTR_RO(cscfg_feat_, nr_params); + +/* base feature desc attrib structures */ +static struct configfs_attribute *cscfg_feature_view_attrs[] = { + &cscfg_feat_attr_description, + &cscfg_feat_attr_matches, + &cscfg_feat_attr_nr_params, + NULL, +}; + +static struct config_item_type cscfg_feature_view_type = { + .ct_owner = THIS_MODULE, + .ct_attrs = cscfg_feature_view_attrs, +}; + +static inline struct cscfg_fs_param *to_cscfg_fs_param_group(struct config_group *group) +{ + return container_of(group, struct cscfg_fs_param, group); +} + +static ssize_t cscfg_param_value_show(struct config_item *item, char *page) +{ + struct cscfg_fs_param *param_item = to_cscfg_fs_param_group(to_config_group(item)); + + return scnprintf(page, PAGE_SIZE, "0x%llx\n", param_item->param->value); +} + +static ssize_t cscfg_param_value_store(struct config_item *item, + const char *page, size_t size) +{ + struct cscfg_fs_param *param_item = to_cscfg_fs_param_group(to_config_group(item)); + u64 val; + int err; + + err = kstrtoull(page, 0, &val); + if (err) + return err; + + spin_lock(¶m_item->desc->param_lock); + param_item->param->value = val; + spin_unlock(¶m_item->desc->param_lock); + + return size; +} +CONFIGFS_ATTR(cscfg_param_, value); + +static struct configfs_attribute *cscfg_param_view_attrs[] = { + &cscfg_param_attr_value, + NULL, +}; + +static struct config_item_type cscfg_param_view_type = { + .ct_owner = THIS_MODULE, + .ct_attrs = cscfg_param_view_attrs, +}; + +static struct config_item_type cscfg_feat_param_group_type = { + .ct_owner = THIS_MODULE, +}; + +/* + * configfs has far less functionality provided to add attributes dynamically than sysfs, + * and the show and store fns pass the enclosing config_item so the actual attribute cannot + * be determined. Therefore we add each item as a group directory, with a value attribute. + */ +static int cscfg_create_params_group_items(struct cscfg_feature_desc *feat_desc, + struct config_group *params_group) +{ + struct device *dev = cscfg_dev_to_dev(); + struct cscfg_fs_param *param_item; + int i; + + /* parameter items - as groups with default_value attribute */ + for (i = 0; i < feat_desc->nr_params; i++) { + param_item = devm_kzalloc(dev, sizeof(struct cscfg_fs_param), GFP_KERNEL); + if (!param_item) + return -ENOMEM; + param_item->desc = feat_desc; + param_item->param = &feat_desc->params[i]; + config_group_init_type_name(¶m_item->group, param_item->param->name, + &cscfg_param_view_type); + configfs_add_default_group(¶m_item->group, params_group); + } + return 0; +} + +static struct config_group *cscfg_create_feature_group(struct cscfg_feature_desc *feat_desc) +{ + struct cscfg_fs_feature *feat_view; + struct device *dev = cscfg_dev_to_dev(); + struct cscfg_fs_def_group *params_group = NULL; + int item_err; + + if (!dev) + return ERR_PTR(-EINVAL); + + feat_view = devm_kzalloc(dev, sizeof(struct cscfg_fs_feature), GFP_KERNEL); + if (!feat_view) + return ERR_PTR(-ENOMEM); + + if (feat_desc->nr_params) { + params_group = devm_kzalloc(dev, sizeof(struct cscfg_fs_feature), GFP_KERNEL); + if (!params_group) + return ERR_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(¶ms_group->group, "params", + &cscfg_feat_param_group_type); + configfs_add_default_group(¶ms_group->group, &feat_view->group); + item_err = cscfg_create_params_group_items(feat_desc, ¶ms_group->group); + if (item_err) + return ERR_PTR(item_err); + } + return &feat_view->group; +} + +static struct config_item_type cscfg_features_type = { + .ct_owner = THIS_MODULE, +}; + +static struct cscfg_fs_def_group cscfg_features_grp = { + .group = { + .cg_item = { + .ci_namebuf = "features", + .ci_type = &cscfg_features_type, + }, + }, +}; + +/* add configuration to configurations group */ +int cscfg_configfs_add_config(struct cscfg_config_desc *cfg_desc) +{ + struct config_group *new_group; + int err; + + new_group = cscfg_create_config_group(cfg_desc); + if (IS_ERR(new_group)) + return PTR_ERR(new_group); + err = configfs_register_group(&cscfg_configs_grp.group, new_group); + return err; +} + +/* add feature to features group */ +int cscfg_configfs_add_feature(struct cscfg_feature_desc *feat_desc) +{ + struct config_group *new_group; + int err; + + new_group = cscfg_create_feature_group(feat_desc); + if (IS_ERR(new_group)) + return PTR_ERR(new_group); + err = configfs_register_group(&cscfg_features_grp.group, new_group); + return err; +} + +static const struct config_item_type syscfg_fs_type = { + .ct_owner = THIS_MODULE, +}; + +static struct cscfg_fs_subsys syscfg_fs_subsys = { + .cfgdev = NULL, + .fs_subsys = { + .su_group = { + .cg_item = { + .ci_namebuf = "coresight-syscfg", + .ci_type = &syscfg_fs_type, + }, + }, + }, +}; + +static inline struct cscfg_device *cscfg_fs_get_cscfg_dev(void) +{ + return syscfg_fs_subsys.cfgdev; +} + +int cscfg_configfs_init(struct cscfg_device *cscfg_dev) +{ + int ret = 0; + struct configfs_subsystem *subsys = &syscfg_fs_subsys.fs_subsys; + + if (!cscfg_dev) + return -EINVAL; + + config_group_init(&subsys->su_group); + mutex_init(&subsys->su_mutex); + + /* Add default groups to subsystem */ + config_group_init(&cscfg_configs_grp.group); + configfs_add_default_group(&cscfg_configs_grp.group, &subsys->su_group); + + config_group_init(&cscfg_features_grp.group); + configfs_add_default_group(&cscfg_features_grp.group, &subsys->su_group); + + ret = configfs_register_subsystem(subsys); + if (!ret) { + syscfg_fs_subsys.cfgdev = cscfg_dev; + cscfg_dev->cfgfs_subsys = &syscfg_fs_subsys; + } + + return ret; +} + +void cscfg_configfs_release(struct cscfg_device *cscfg_dev) +{ + if (cscfg_dev && cscfg_dev->cfgfs_subsys) { + configfs_unregister_subsystem(&cscfg_dev->cfgfs_subsys->fs_subsys); + cscfg_dev->cfgfs_subsys = NULL; + } + syscfg_fs_subsys.cfgdev = NULL; +} diff --git a/drivers/hwtracing/coresight/coresight-syscfg-configfs.h b/drivers/hwtracing/coresight/coresight-syscfg-configfs.h new file mode 100644 index 000000000000..70cc3745649e --- /dev/null +++ b/drivers/hwtracing/coresight/coresight-syscfg-configfs.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Coresight system configuration driver - support for configfs. + */ + +#ifndef CORESIGHT_SYSCFG_CONFIGFS_H +#define CORESIGHT_SYSCFG_CONFIGFS_H + +#include +#include "coresight-syscfg.h" + +/* container to associate the device and configfs subsystem */ +struct cscfg_fs_subsys { + struct cscfg_device *cfgdev; + struct configfs_subsystem fs_subsys; +}; + +/* container for default groups */ +struct cscfg_fs_def_group { + struct config_group group; +}; + +/* container for configuration view */ +struct cscfg_fs_config { + struct cscfg_config_desc *desc; + struct config_group group; +}; + +/* container for feature view */ +struct cscfg_fs_feature { + struct cscfg_feature_desc *desc; + struct config_group group; +}; + +/* container for parameter view */ +struct cscfg_fs_param { + struct cscfg_parameter_desc *param; + struct cscfg_feature_desc *desc; + struct config_group group; +}; + +int cscfg_configfs_init(struct cscfg_device *dev); +void cscfg_configfs_release(struct cscfg_device *dev); +int cscfg_configfs_add_config(struct cscfg_config_desc *cfg_desc); +int cscfg_configfs_add_feature(struct cscfg_feature_desc *feat_desc); + +#endif /* CORESIGHT_SYSCFG_CONFIGFS_H */ diff --git a/drivers/hwtracing/coresight/coresight-syscfg.c b/drivers/hwtracing/coresight/coresight-syscfg.c index 8d52580daf04..2cf67a038cc8 100644 --- a/drivers/hwtracing/coresight/coresight-syscfg.c +++ b/drivers/hwtracing/coresight/coresight-syscfg.c @@ -9,6 +9,7 @@ #include "coresight-config.h" #include "coresight-etm-perf.h" #include "coresight-syscfg.h" +#include "coresight-syscfg-configfs.h" /* * cscfg_ API manages configurations and features for the entire coresight @@ -260,6 +261,8 @@ static int cscfg_load_feat(struct cscfg_feature_desc *feat_desc) { int err; + spin_lock_init(&feat_desc->param_lock); + /* add feature to any matching registered devices */ err = cscfg_add_feat_to_csdevs(feat_desc); if (err) @@ -294,6 +297,24 @@ static int cscfg_load_config(struct cscfg_config_desc *cfg_desc) return err; } +/* get a feature descriptor by name */ +const struct cscfg_feature_desc *cscfg_get_named_feat_desc(const char *name) +{ + const struct cscfg_feature_desc *feat = NULL, *feat_item; + + mutex_lock(&cscfg_mutex); + + list_for_each_entry(feat_item, &cscfg_data.feat_list, item) { + if (strcmp(feat_item->name, name) == 0) { + feat = feat_item; + break; + } + } + + mutex_unlock(&cscfg_mutex); + return feat; +} + /* * External API function to load feature and config sets. * Take a 0 terminated array of feature descriptors and/or configuration @@ -316,6 +337,7 @@ int cscfg_load_config_sets(struct cscfg_config_desc **cfg_descs, feat_descs[i]->name); goto do_unlock; } + cscfg_configfs_add_feature(feat_descs[i]); i++; } } @@ -330,6 +352,7 @@ int cscfg_load_config_sets(struct cscfg_config_desc **cfg_descs, cfg_descs[i]->name); goto do_unlock; } + cscfg_configfs_add_config(cfg_descs[i]); i++; } } @@ -502,6 +525,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_dev); kfree(cscfg_dev); cscfg_dev = NULL; } @@ -530,6 +554,7 @@ int cscfg_create_device(void) cscfg_dev->cfg_data = &cscfg_data; err = device_register(dev); + if (err) cscfg_dev_release(dev); @@ -587,6 +612,10 @@ int __init cscfg_init(void) if (err) goto exit_drv_unregister; + err = cscfg_configfs_init(cscfg_dev); + if (err) + goto exit_dev_clear; + INIT_LIST_HEAD(&cscfg_data.dev_list); INIT_LIST_HEAD(&cscfg_data.feat_list); INIT_LIST_HEAD(&cscfg_data.config_list); @@ -595,6 +624,8 @@ int __init cscfg_init(void) dev_info(to_device_cscfg(), "CoreSight Configuration manager initialised"); return 0; +exit_dev_clear: + cscfg_clear_device(); exit_drv_unregister: cscfg_driver_exit(); exit_bus_unregister: diff --git a/drivers/hwtracing/coresight/coresight-syscfg.h b/drivers/hwtracing/coresight/coresight-syscfg.h index e8f352599dd7..ce237a69677b 100644 --- a/drivers/hwtracing/coresight/coresight-syscfg.h +++ b/drivers/hwtracing/coresight/coresight-syscfg.h @@ -6,6 +6,7 @@ #ifndef CORESIGHT_SYSCFG_H #define CORESIGHT_SYSCFG_H +#include #include #include @@ -46,6 +47,7 @@ struct cscfg_csdev_register { int __init cscfg_init(void); void __exit cscfg_exit(void); int cscfg_preload(void); +const struct cscfg_feature_desc *cscfg_get_named_feat_desc(const char *name); /* syscfg external API */ int cscfg_load_config_sets(struct cscfg_config_desc **cfg_descs, @@ -64,10 +66,12 @@ void cscfg_unregister_csdev(struct coresight_device *csdev); * * @dev: The device. * @cfg_data: A reference to the configuration and feature lists + * @cfgfs_subsys: configfs subsystem used to manage configurations. */ struct cscfg_device { struct device dev; struct cscfg_api_data *cfg_data; + struct cscfg_fs_subsys *cfgfs_subsys; }; /* basic device driver */ From patchwork Fri Oct 30 17:56:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Leach X-Patchwork-Id: 11870461 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D7BB1C00A89 for ; Fri, 30 Oct 2020 17:59:34 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 4DE1620A8B for ; Fri, 30 Oct 2020 17:59:34 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="oE24SGFU"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="lQDOenwp" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 4DE1620A8B Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:MIME-Version:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:References:In-Reply-To:Message-Id:Date:Subject:To: From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=ucZPdN0SjoL1c47IOB3Etx+uamUP93JJP4pyw3QaidA=; b=oE24SGFUyfNuzpYta74J2I51Jx eEdN/xl4n4vkGS8Q1fV/FOfrO7GydLzK+jTXvnWMZ+Ja5yDUTALvyVclhG3aeON4d9LbLmPq3w7I8 DyHMMIr5xCqliJ7FGijlxtroAdvTB9ZZhBte8OM0+eJPpOjjkC/IMIpy4o+28FUXIoHsD/rOt1pee 7f2AHBibJwiLPT9RiVfBkVrH8yO9GF5f7w8s4mv9wP8mskz8aqbbvtk4cB13E6L4pLwWgzENCXMTH 08BWLyM7dzlZiEK45+G66CCY9cf4Zoodbkvz9fbp6t0Z6uxgJ1bOFAO7kX/v1P/PRPldunBr3m74k 8h+uzqbg==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kYYeg-0003vI-TJ; Fri, 30 Oct 2020 17:57:39 +0000 Received: from mail-wm1-x342.google.com ([2a00:1450:4864:20::342]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kYYeB-0003mg-Fz for linux-arm-kernel@lists.infradead.org; Fri, 30 Oct 2020 17:57:14 +0000 Received: by mail-wm1-x342.google.com with SMTP id k18so3718151wmj.5 for ; Fri, 30 Oct 2020 10:57:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=GGKTje4jPOjb3VM6X5bDiYCSOQcsfHSNonQFBEGHAUE=; b=lQDOenwpVy++4FjT95IudNOY4MANv3ii/sT2gaC9qEnZd3TmEw5aUrTHbi92D34Pds QKEMmVsUDrZ/FEKv2GxvpwwV6HLDf+3cw5zWw1U/t3AOQZRyDICz2B9WlvxCZuYaWfVc gYJZylgBE7k3Iv5TATIhMvX3QvT8WpIofY3IEyaw2Ue4xx9Otou1l20VtFknrc3IqBWX ZIF1WrqHqNV8D2Rvls4U3SRsibqM13L42W9akF17e1zAJuuJ2VA3DbTKR3M8QcJ9hzR9 gO1y295im5inD/CEVhxS54F82cbg9npMdeSks5v/8TIgNnCUlHhHnX4vxdqQ1zaUAxeW +aCA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=GGKTje4jPOjb3VM6X5bDiYCSOQcsfHSNonQFBEGHAUE=; b=Gy5PEvLsyfIg6Q47cMGbiqIiHYuqAtXb5w1pLKSd09yDo1kNr1HYoTw+Qmf5OtC/kG hnuPqAfUXPp/E7+o06OVLMZk2BfZBOPOjJ286+KwvBR4zGQbHdbtfWllxQG/SwRZpC6M tFpXmgx8ZDZUKpN4WC/MHD1609Hifs4MbXc0JvaROnQyo7kMWsYNx8YpgpQRi+1lhGTH VM4LtqBsqo+tFML+rLHiHrknSlG218ifIUsg+AF/186oMtRz7aayN1z/e/aygHkQrVm5 hvYqa49iu3uKz8XJ6gxhJwltUQp1cQeRMUTPuw9Iu1bGNSRiv0GamaTOo4J3mplK07iu lVnw== X-Gm-Message-State: AOAM531mvjR1RLDo27y3VdLHU5/CMaBHr0rILL4ZsdFH0HejGFyzHrwD bMq0LpeDV/1QJCFXPaRoL63faaykUH5wMw== X-Google-Smtp-Source: ABdhPJxCAf4AKrzxwWwh55W3x6oYkylHgFdeMfrlWM7+GitPiWkGt+4rZQMlc/93AWxFbue2XZUwNQ== X-Received: by 2002:a1c:3846:: with SMTP id f67mr4129432wma.33.1604080626230; Fri, 30 Oct 2020 10:57:06 -0700 (PDT) Received: from linaro.org ([2a00:23c5:6801:1801:4964:83f8:d2e7:f2c9]) by smtp.gmail.com with ESMTPSA id o129sm5615563wmb.25.2020.10.30.10.57.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 30 Oct 2020 10:57:05 -0700 (PDT) From: Mike Leach To: linux-arm-kernel@lists.infradead.org, coresight@lists.linaro.org, mathieu.poirier@linaro.org Subject: [RFC PATCH v3 8/9] coresight: syscfg: Allow update of feature params from configfs Date: Fri, 30 Oct 2020 17:56:54 +0000 Message-Id: <20201030175655.30126-9-mike.leach@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201030175655.30126-1-mike.leach@linaro.org> References: <20201030175655.30126-1-mike.leach@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201030_135708_675476_BCD3DB50 X-CRM114-Status: GOOD ( 22.22 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: yabinc@google.com, Mike Leach , suzuki.poulose@arm.com MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add in functionality to allow the user to update feature default parameter values from the configfs interface. This updates all the device instances with the new values, removing the need to set all devices individually via sysfs. Signed-off-by: Mike Leach --- .../hwtracing/coresight/coresight-config.c | 36 ++++++++++++++++--- .../hwtracing/coresight/coresight-config.h | 1 + .../coresight/coresight-syscfg-configfs.c | 3 ++ .../hwtracing/coresight/coresight-syscfg.c | 15 ++++++++ .../hwtracing/coresight/coresight-syscfg.h | 1 + 5 files changed, 52 insertions(+), 4 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-config.c b/drivers/hwtracing/coresight/coresight-config.c index 04e7cb4ff769..7d30a415f2ff 100644 --- a/drivers/hwtracing/coresight/coresight-config.c +++ b/drivers/hwtracing/coresight/coresight-config.c @@ -96,6 +96,17 @@ static void cscfg_save_on_disable(struct cscfg_feature_csdev *feat, const bool f spin_unlock(feat->csdev_spinlock); } +/* load default values into params */ +static void cscfg_set_param_defaults(struct cscfg_feature_csdev *feat) +{ + int i; + + spin_lock(&feat->desc->param_lock); + for (i = 0; i < feat->nr_params; i++) + feat->params[i].current_value = feat->desc->params[i].value; + spin_unlock(&feat->desc->param_lock); +} + /* default reset - restore default values, disable feature */ static void cscfg_reset_feat(struct cscfg_feature_csdev *feat) { @@ -111,10 +122,7 @@ static void cscfg_reset_feat(struct cscfg_feature_csdev *feat) * set the default values for all parameters and regs from the * relevant static descriptors. */ - spin_lock(&feat->desc->param_lock); - for (i = 0; i < feat->nr_params; i++) - feat->params[i].current_value = feat->desc->params[i].value; - spin_unlock(&feat->desc->param_lock); + cscfg_set_param_defaults(feat); for (i = 0; i < feat->nr_regs; i++) { reg_desc = &feat->desc->regs[i]; @@ -131,6 +139,26 @@ static void cscfg_reset_feat(struct cscfg_feature_csdev *feat) spin_unlock(feat->csdev_spinlock); } +/* update the parameters in a named feature from their defaults for the supplied device */ +void cscfg_csdev_set_param_defaults(struct coresight_device *csdev, const char *feat_name) +{ + struct cscfg_feature_csdev *feat; + + spin_lock(&csdev->cfg_lock); + if (list_empty(&csdev->feat_list)) { + spin_unlock(&csdev->cfg_lock); + return; + } + + list_for_each_entry(feat, &csdev->feat_list, node) { + if (!strcmp(feat_name, feat->desc->name)) { + cscfg_set_param_defaults(feat); + break; + } + } + spin_unlock(&csdev->cfg_lock); +} + void cscfg_set_def_ops(struct cscfg_feature_csdev *feat) { feat->ops.set_on_enable = cscfg_set_on_enable; diff --git a/drivers/hwtracing/coresight/coresight-config.h b/drivers/hwtracing/coresight/coresight-config.h index 39fcac011aa0..1c6f0f903861 100644 --- a/drivers/hwtracing/coresight/coresight-config.h +++ b/drivers/hwtracing/coresight/coresight-config.h @@ -297,6 +297,7 @@ struct cscfg_csdev_feat_ops { /* helper functions for feature manipulation */ void cscfg_set_def_ops(struct cscfg_feature_csdev *feat); +void cscfg_csdev_set_param_defaults(struct coresight_device *csdev, const char *feat_name); /* enable / disable features or configs on a device */ int cscfg_csdev_set_enabled_feats(struct coresight_device *csdev); diff --git a/drivers/hwtracing/coresight/coresight-syscfg-configfs.c b/drivers/hwtracing/coresight/coresight-syscfg-configfs.c index ff7ea678100a..1595c0c61db1 100644 --- a/drivers/hwtracing/coresight/coresight-syscfg-configfs.c +++ b/drivers/hwtracing/coresight/coresight-syscfg-configfs.c @@ -242,6 +242,9 @@ static ssize_t cscfg_param_value_store(struct config_item *item, param_item->param->value = val; spin_unlock(¶m_item->desc->param_lock); + /* push new value out to devices */ + cscfg_update_named_feat_csdevs(param_item->desc->name); + return size; } CONFIGFS_ATTR(cscfg_param_, value); diff --git a/drivers/hwtracing/coresight/coresight-syscfg.c b/drivers/hwtracing/coresight/coresight-syscfg.c index 2cf67a038cc8..c42374342806 100644 --- a/drivers/hwtracing/coresight/coresight-syscfg.c +++ b/drivers/hwtracing/coresight/coresight-syscfg.c @@ -315,6 +315,21 @@ const struct cscfg_feature_desc *cscfg_get_named_feat_desc(const char *name) return feat; } +/* + * Set all parameter defaults for named feature. + * Iterates through csdev list and updates param defaults on named feature. + */ +void cscfg_update_named_feat_csdevs(const char *feat_name) +{ + struct cscfg_csdev_register *curr_item; + + mutex_lock(&cscfg_mutex); + list_for_each_entry(curr_item, &cscfg_data.dev_list, item) { + cscfg_csdev_set_param_defaults(curr_item->csdev, feat_name); + } + mutex_unlock(&cscfg_mutex); +} + /* * External API function to load feature and config sets. * Take a 0 terminated array of feature descriptors and/or configuration diff --git a/drivers/hwtracing/coresight/coresight-syscfg.h b/drivers/hwtracing/coresight/coresight-syscfg.h index ce237a69677b..d07a0f11097f 100644 --- a/drivers/hwtracing/coresight/coresight-syscfg.h +++ b/drivers/hwtracing/coresight/coresight-syscfg.h @@ -48,6 +48,7 @@ int __init cscfg_init(void); void __exit cscfg_exit(void); int cscfg_preload(void); const struct cscfg_feature_desc *cscfg_get_named_feat_desc(const char *name); +void cscfg_update_named_feat_csdevs(const char *feat_name); /* syscfg external API */ int cscfg_load_config_sets(struct cscfg_config_desc **cfg_descs, From patchwork Fri Oct 30 17:56:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Leach X-Patchwork-Id: 11870459 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-17.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,MENTIONS_GIT_HOSTING,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS, URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id EDD0BC00A89 for ; Fri, 30 Oct 2020 17:59:27 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 1A89820724 for ; Fri, 30 Oct 2020 17:59:27 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="P8hg5/JE"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="QhIhc6BJ" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 1A89820724 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:MIME-Version:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:References:In-Reply-To:Message-Id:Date:Subject:To: From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=tIKj5P42EkvGCBtNjHjyD4VxG/vG5iVL+zoEHVX/3sk=; b=P8hg5/JEPdAJ/fAFEEkD9b7lan Bh16LYZA44sJpN9Bz00bt+jZn8ntvPbSLg4pig/R/rnj/IghSoI3quGPBH5mOe4KRGNQmL0/S3yss vFbo4G9vsAWFUPYPR7GpnSnC5Ec5ezeYEaPZCSbtQYpjsPwkM1PYi4y+r7ct/mjWwDUQvNfToc3WF vOwAnsJpug5BbPdrT0yVxBCcTqwPqSQVfzEF6yk5TzjovBp5NuPZ63542T6/vg04BizR4of266uCB VcFSoS9QDAL+EVXrvW5YNT6LHFq6Orpt2mkARm74kOmZG7/4NcMOVRUR8Uo31JJm9Mx/Nbl/YLLoq 4mohviRQ==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kYYfm-0004J3-B6; Fri, 30 Oct 2020 17:58:46 +0000 Received: from mail-wm1-x32d.google.com ([2a00:1450:4864:20::32d]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kYYeD-0003mk-1F for linux-arm-kernel@lists.infradead.org; Fri, 30 Oct 2020 17:57:15 +0000 Received: by mail-wm1-x32d.google.com with SMTP id h22so3746133wmb.0 for ; Fri, 30 Oct 2020 10:57:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=VoGovKEbbz2tGOPajOqOeaPAgxytepmpu53NKthUheI=; b=QhIhc6BJ9W+kE3BH45fjsnCC5vKgb3GXuEi30QfsdwtNZyJrjfZkZvVF6knbp0qiJF Qf+DpiHNsES8FgqZJ27hkkMzPEObNdV+LFS/jn/F6Gun64LvtKynL2g82nYVbLVgfvS9 eeL5QvlKHwBwo4rEl53LCBbXndtXM4fsEqGlA28IRinymlVH4HWgF6XHAMdiLOBMCFI2 2KfZHRl8KM1MQOBflmVGnP2LAuhlthl1DgEB/X+HdrRR67FGP70RvUEc8hjSUUzI7PAs OOckYF35+QKb7lbb/87CMJkHzQDG5SKtxv11gPHqvfvN73ICqrbUf/Z1f4Zp+tSXzTC2 RRhw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=VoGovKEbbz2tGOPajOqOeaPAgxytepmpu53NKthUheI=; b=dIJ+RiyMS1vFpjSQeQIil8dMzxNq9nsJAdsv6j5NhX8yun06yyPn0QTpSbrDS5WuBs x8TJwYAdGBOvOG3NyJCbm/Jf4nxvwZoaillG0H+IvRVBup0fuqMudiJAcLJ2ig+0a9ns SuwfrVZnjNKb/5Gd3CwX3AwLhO2zvwby2/K6J9HMrh0ddVVBkkcHgONcAIDsagphPAEE r/aYPouwiSCXsFOxyTXtOZNsdfAa7A/bvrOtPhYLXZq9oNuzdp3D8+AqXIR0htqOKJ0f Rt/fyj8gOMX7PHPKU/oXvKyqXM2HSP7OivWhTokHhiwdhsOeDZLty3gxrKknVIMk+VR8 ryGw== X-Gm-Message-State: AOAM531NzzudbVQMuAj/imAA71LPjrWy/ICoEL6d9FPZyOZik74WV1kh k+vzvfsL45HxsUQuqll4kdhTYvL8I4sEEQ== X-Google-Smtp-Source: ABdhPJxl19LagFzxGRcBuhMUWVuPx5MeeCYEALYaR3iylSGXI6z6U1WyZnJdhoaApApXn5JLQml+/A== X-Received: by 2002:a7b:cc09:: with SMTP id f9mr3960554wmh.93.1604080627121; Fri, 30 Oct 2020 10:57:07 -0700 (PDT) Received: from linaro.org ([2a00:23c5:6801:1801:4964:83f8:d2e7:f2c9]) by smtp.gmail.com with ESMTPSA id o129sm5615563wmb.25.2020.10.30.10.57.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 30 Oct 2020 10:57:06 -0700 (PDT) From: Mike Leach To: linux-arm-kernel@lists.infradead.org, coresight@lists.linaro.org, mathieu.poirier@linaro.org Subject: [RFC PATCH v3 9/9] coresight: docs: Add documentation for CoreSight config. Date: Fri, 30 Oct 2020 17:56:55 +0000 Message-Id: <20201030175655.30126-10-mike.leach@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201030175655.30126-1-mike.leach@linaro.org> References: <20201030175655.30126-1-mike.leach@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201030_135709_217783_4D35C6AB X-CRM114-Status: GOOD ( 29.63 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: yabinc@google.com, Mike Leach , suzuki.poulose@arm.com MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Adds documentation for the CoreSight System configuration manager. Signed-off-by: Mike Leach --- .../trace/coresight/coresight-config.rst | 230 ++++++++++++++++++ Documentation/trace/coresight/coresight.rst | 16 ++ 2 files changed, 246 insertions(+) create mode 100644 Documentation/trace/coresight/coresight-config.rst diff --git a/Documentation/trace/coresight/coresight-config.rst b/Documentation/trace/coresight/coresight-config.rst new file mode 100644 index 000000000000..8afcf18c090c --- /dev/null +++ b/Documentation/trace/coresight/coresight-config.rst @@ -0,0 +1,230 @@ +.. SPDX-License-Identifier: GPL-2.0 + +====================================== +CoreSight System Configuration Manager +====================================== + + :Author: Mike Leach + :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 complex 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 +device is registered with the configuration manager. + +The load process involves interpreting the descriptor into a the 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 can be enabled either as part of a configuration being enabled on the +system, or individually on a device instance using the configfs API. + + +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. + + +Virtual Device +-------------- + +The CoreSight System Configuration manager also includes a virtual CoreSight +device. This provides the system with access to kernel objects and device +management to own elements such as the sysfs entries used to expose the +configurations into the cs_etm event in perf. + +This device 'system_cfg' appears on a custom bus - 'coresight-config' - +rather than the normal 'coresight' bus to avoid complications when the +coresight system is searching for real devices on the bus. + + +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 nr_presets preset_values refs + $ cat description + Setup ETMs with strobing for autofdo + $ cat refs + references 1 features:- + strobing + $ cat nr_presets + 2 + $ cat preset_values + 2 presets, 2 parameters per preset + preset[1]: strobing.window = 0x2710 strobing.period = 0x1388 + preset[2]: strobing.window = 0x1388 strobing.period = 0x1388 + +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 + +A preset to override the current parameter values can also be selected:: + + $ perf record -e cs_etm/autofdo,preset=1/u --per-thread + +When configurations are selected in this way, then the trace sink used is +automatically selected. diff --git a/Documentation/trace/coresight/coresight.rst b/Documentation/trace/coresight/coresight.rst index 0b73acb44efa..0122d9bebf35 100644 --- a/Documentation/trace/coresight/coresight.rst +++ b/Documentation/trace/coresight/coresight.rst @@ -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