From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 3529CC433F5 for ; Wed, 24 Nov 2021 20:03:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:List-Subscribe:List-Help: List-Post:List-Archive:List-Unsubscribe:List-Id:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=GpDLARbNcxRnkdyhl1lP/74yFS/RbbWvOmbp+habE4I=; b=tClL4SijAYicw5 QxodyYvL6GG+pXNcwn5/5PU7tzsOgcCDoFYSKXyXURxl6xA1XEyZLM06+2A1Ws1v3+hcHiOXixjAY DkMd+aybcFn3tEht+lPgSLc56JY1cTT3p5YrfTzhky4q+eOzN50YR5Da0LvtHTAVYs3dThoe4DdkU xBvq+uKLggX3Z66v2pqTMZdR4FT8VjOiMCUtBIHAayG6e6e12T3oX1leehH8AFNH5Qqb9T7JciBuN xSkmq+bEXi+nfKsZwxI8Mi8smpOa2FQeog9Wy/2QU/ifWEa84sspRqAwLdNhFvW/avLUYlMBfCWfr RjhN3Kawtais/qTsvRvQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mpySo-005jnS-4h; Wed, 24 Nov 2021 20:01:54 +0000 Received: from mail-wm1-x331.google.com ([2a00:1450:4864:20::331]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mpyRj-005jR8-9J for linux-arm-kernel@lists.infradead.org; Wed, 24 Nov 2021 20:00:50 +0000 Received: by mail-wm1-x331.google.com with SMTP id g191-20020a1c9dc8000000b0032fbf912885so3041788wme.4 for ; Wed, 24 Nov 2021 12:00:46 -0800 (PST) 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=/0sMKWlKHEGZZmerIoHeR8BNRmG+vaThpY3WRjo3Zws=; b=Omi55R0pLvpbOWRiQO+nAkuCp28dkIRdD62u6JXh+dxF7diALeguN5XBlYx4fpRVzy BBZUc+555KUoVH2jyl+LvaFLJKPSF9bTKZk8VlgPIXPZeTf0rz74RNnTahBRX8D2SJ07 h5XqQVBJMlnX+U5txG8RjYn204PZ1iKIRa0BWyYlw9GioKGTefAOwD0DsrIfYMmYpVvk cgMYk7wCukeDz9WBsh7WKMxohEIC/aouazKGZDAAwzf6TXmBrWNMThL0ykCcH0uUgHKA B7gldXzYwVxNWIEH65KY9iHG6vEgg6nI6tff5s8xVrJ6D02j8hVgxm4DWY4jHuiXfjIN sD6w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=/0sMKWlKHEGZZmerIoHeR8BNRmG+vaThpY3WRjo3Zws=; b=NQdwJwrQwmJFEq3F2kwWx1Q3jo/S5VrRD0vr/RyDrW9FyvKv04Jzn5zKDF/lX6f2K1 n+zBTiE0wLE+7FlCoGqAA9wVRCuJ++j7OnelmOzgpO4ph7/xKvT2IFUTYjzc05ktK6pn J9nH1lxq0QmdJiawCngruvG+EF0iuT+HluGqXv+AVZ9/fWVsGEYqpUdzYrb1GOioc96H 37M6KJiQQvrpdz538WzK8xcXijh3hNO6JOTLS3ucIdsg+n51s9xPLvPsSiMZnhXFZkoF tQtXel82hy7LnkDtyAyX/ghtY+Dw26lYBh0S03eZs2x4ifUO0Q7PhXTmsU/4/ACsbfkD 0/6w== X-Gm-Message-State: AOAM531MQt9eyfJEGb4zjRrdWwrqsWYL8GLT4agbMGz+mFnTSHOzSCOU cnIDUY2iNft8s56SibwvLrA9AW61heeDKQ== X-Google-Smtp-Source: ABdhPJyg1oqq9yUFZVWxmulIuQZyc52d2DpdnZyacyAYKCU4YqgL37Lyt37wK0DGAS4wVUaTfBmVUg== X-Received: by 2002:a7b:c119:: with SMTP id w25mr18838670wmi.70.1637784045768; Wed, 24 Nov 2021 12:00:45 -0800 (PST) Received: from linaro.org ([2a00:23c5:6809:2201:dd2e:a6e1:6adf:269c]) by smtp.gmail.com with ESMTPSA id c1sm729582wrt.14.2021.11.24.12.00.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 24 Nov 2021 12:00:45 -0800 (PST) From: Mike Leach To: linux-arm-kernel@lists.infradead.org, coresight@lists.linaro.org Cc: mathieu.poirier@linaro.org, suzuki.poulose@arm.com, leo.yan@linaro.org, Mike Leach Subject: [PATCH v3 2/6] coresight: configuration: Update API to permit dynamic load/unload Date: Wed, 24 Nov 2021 20:00:34 +0000 Message-Id: <20211124200038.28662-3-mike.leach@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20211124200038.28662-1-mike.leach@linaro.org> References: <20211124200038.28662-1-mike.leach@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211124_120047_359390_449C0F3C X-CRM114-Status: GOOD ( 25.19 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Expand the configuration API to allow dynamic runtime load and unload of configurations and features. On load, configurations and features are tagged with a "load owner" that is used to determine sets that were loaded together in a given API call. To unload the API uses the load owner to unload all elements previously loaded by that owner. The API also records the order in which different owners loaded their elements into the system. Later loading configurations can use previously loaded features, creating load dependencies. Therefore unload is enforced strictly in the reverse order to load. A load owner will be an additional loadable module, or a configuration loaded via configfs. Signed-off-by: Mike Leach Reviewed-by: Mathieu Poirier --- .../hwtracing/coresight/coresight-config.h | 4 + .../coresight/coresight-syscfg-configfs.c | 20 +++ .../coresight/coresight-syscfg-configfs.h | 2 + .../hwtracing/coresight/coresight-syscfg.c | 133 ++++++++++++++++++ .../hwtracing/coresight/coresight-syscfg.h | 1 + 5 files changed, 160 insertions(+) diff --git a/drivers/hwtracing/coresight/coresight-config.h b/drivers/hwtracing/coresight/coresight-config.h index 6e0d43901d66..9bd44b940add 100644 --- a/drivers/hwtracing/coresight/coresight-config.h +++ b/drivers/hwtracing/coresight/coresight-config.h @@ -98,6 +98,7 @@ struct cscfg_regval_desc { * @nr_regs: number of registers used. * @regs_desc: array of registers used. * @load_owner: handle to load owner for dynamic load and unload of features. + * @fs_group: reference to configfs group for dynamic unload. */ struct cscfg_feature_desc { const char *name; @@ -109,6 +110,7 @@ struct cscfg_feature_desc { int nr_regs; struct cscfg_regval_desc *regs_desc; void *load_owner; + struct config_group *fs_group; }; /** @@ -131,6 +133,7 @@ struct cscfg_feature_desc { * @event_ea: Extended attribute for perf event value * @active_cnt: ref count for activate on this configuration. * @load_owner: handle to load owner for dynamic load and unload of configs. + * @fs_group: reference to configfs group for dynamic unload. */ struct cscfg_config_desc { const char *name; @@ -144,6 +147,7 @@ struct cscfg_config_desc { struct dev_ext_attribute *event_ea; atomic_t active_cnt; void *load_owner; + struct config_group *fs_group; }; /** diff --git a/drivers/hwtracing/coresight/coresight-syscfg-configfs.c b/drivers/hwtracing/coresight/coresight-syscfg-configfs.c index c547816b9000..345a62f1b728 100644 --- a/drivers/hwtracing/coresight/coresight-syscfg-configfs.c +++ b/drivers/hwtracing/coresight/coresight-syscfg-configfs.c @@ -334,9 +334,19 @@ int cscfg_configfs_add_config(struct cscfg_config_desc *config_desc) if (IS_ERR(new_group)) return PTR_ERR(new_group); err = configfs_register_group(&cscfg_configs_grp, new_group); + if (!err) + config_desc->fs_group = new_group; return err; } +void cscfg_configfs_del_config(struct cscfg_config_desc *config_desc) +{ + if (config_desc->fs_group) { + configfs_unregister_group(config_desc->fs_group); + config_desc->fs_group = NULL; + } +} + static struct config_item_type cscfg_features_type = { .ct_owner = THIS_MODULE, }; @@ -358,9 +368,19 @@ int cscfg_configfs_add_feature(struct cscfg_feature_desc *feat_desc) if (IS_ERR(new_group)) return PTR_ERR(new_group); err = configfs_register_group(&cscfg_features_grp, new_group); + if (!err) + feat_desc->fs_group = new_group; return err; } +void cscfg_configfs_del_feature(struct cscfg_feature_desc *feat_desc) +{ + if (feat_desc->fs_group) { + configfs_unregister_group(feat_desc->fs_group); + feat_desc->fs_group = NULL; + } +} + int cscfg_configfs_init(struct cscfg_manager *cscfg_mgr) { struct configfs_subsystem *subsys; diff --git a/drivers/hwtracing/coresight/coresight-syscfg-configfs.h b/drivers/hwtracing/coresight/coresight-syscfg-configfs.h index 7d6ffe35ca4c..ea1e54d29f7f 100644 --- a/drivers/hwtracing/coresight/coresight-syscfg-configfs.h +++ b/drivers/hwtracing/coresight/coresight-syscfg-configfs.h @@ -41,5 +41,7 @@ int cscfg_configfs_init(struct cscfg_manager *cscfg_mgr); void cscfg_configfs_release(struct cscfg_manager *cscfg_mgr); int cscfg_configfs_add_config(struct cscfg_config_desc *config_desc); int cscfg_configfs_add_feature(struct cscfg_feature_desc *feat_desc); +void cscfg_configfs_del_config(struct cscfg_config_desc *config_desc); +void cscfg_configfs_del_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 021f50949d7b..8bff7da1aab2 100644 --- a/drivers/hwtracing/coresight/coresight-syscfg.c +++ b/drivers/hwtracing/coresight/coresight-syscfg.c @@ -250,6 +250,13 @@ static int cscfg_check_feat_for_cfg(struct cscfg_config_desc *config_desc) static int cscfg_load_feat(struct cscfg_feature_desc *feat_desc) { int err; + struct cscfg_feature_desc *feat_desc_exist; + + /* new feature must have unique name */ + list_for_each_entry(feat_desc_exist, &cscfg_mgr->feat_desc_list, item) { + if (!strcmp(feat_desc_exist->name, feat_desc->name)) + return -EEXIST; + } /* add feature to any matching registered devices */ err = cscfg_add_feat_to_csdevs(feat_desc); @@ -267,6 +274,13 @@ static int cscfg_load_feat(struct cscfg_feature_desc *feat_desc) static int cscfg_load_config(struct cscfg_config_desc *config_desc) { int err; + struct cscfg_config_desc *config_desc_exist; + + /* new configuration must have a unique name */ + list_for_each_entry(config_desc_exist, &cscfg_mgr->config_desc_list, item) { + if (!strcmp(config_desc_exist->name, config_desc->name)) + return -EEXIST; + } /* validate features are present */ err = cscfg_check_feat_for_cfg(config_desc); @@ -354,6 +368,72 @@ int cscfg_update_feat_param_val(struct cscfg_feature_desc *feat_desc, return err; } +static void cscfg_remove_owned_csdev_configs(struct coresight_device *csdev, void *load_owner) +{ + struct cscfg_config_csdev *config_csdev, *tmp; + + if (list_empty(&csdev->config_csdev_list)) + return; + + list_for_each_entry_safe(config_csdev, tmp, &csdev->config_csdev_list, node) { + if (config_csdev->config_desc->load_owner == load_owner) + list_del(&config_csdev->node); + } +} + +static void cscfg_remove_owned_csdev_features(struct coresight_device *csdev, void *load_owner) +{ + struct cscfg_feature_csdev *feat_csdev, *tmp; + + if (list_empty(&csdev->feature_csdev_list)) + return; + + list_for_each_entry_safe(feat_csdev, tmp, &csdev->feature_csdev_list, node) { + if (feat_csdev->feat_desc->load_owner == load_owner) + list_del(&feat_csdev->node); + } +} + +/* + * removal is relatively easy - just remove from all lists, anything that + * matches the owner. Memory for the descriptors will be managed by the owner, + * memory for the csdev items is devm_ allocated with the individual csdev + * devices. + */ +static void cscfg_unload_owned_cfgs_feats(void *load_owner) +{ + struct cscfg_config_desc *config_desc, *cfg_tmp; + struct cscfg_feature_desc *feat_desc, *feat_tmp; + struct cscfg_registered_csdev *csdev_item; + + /* remove from each csdev instance feature and config lists */ + list_for_each_entry(csdev_item, &cscfg_mgr->csdev_desc_list, item) { + /* + * for each csdev, check the loaded lists and remove if + * referenced descriptor is owned + */ + cscfg_remove_owned_csdev_configs(csdev_item->csdev, load_owner); + cscfg_remove_owned_csdev_features(csdev_item->csdev, load_owner); + } + + /* remove from the config descriptor lists */ + list_for_each_entry_safe(config_desc, cfg_tmp, &cscfg_mgr->config_desc_list, item) { + if (config_desc->load_owner == load_owner) { + cscfg_configfs_del_config(config_desc); + etm_perf_del_symlink_cscfg(config_desc); + list_del(&config_desc->item); + } + } + + /* remove from the feature descriptor lists */ + list_for_each_entry_safe(feat_desc, feat_tmp, &cscfg_mgr->feat_desc_list, item) { + if (feat_desc->load_owner == load_owner) { + cscfg_configfs_del_feature(feat_desc); + list_del(&feat_desc->item); + } + } +} + /** * cscfg_load_config_sets - API function to load feature and config sets. * @@ -389,6 +469,7 @@ int cscfg_load_config_sets(struct cscfg_config_desc **config_descs, if (err) { pr_err("coresight-syscfg: Failed to load feature %s\n", feat_descs[i]->name); + cscfg_unload_owned_cfgs_feats(owner_info); goto exit_unlock; } feat_descs[i]->load_owner = owner_info; @@ -406,6 +487,7 @@ int cscfg_load_config_sets(struct cscfg_config_desc **config_descs, if (err) { pr_err("coresight-syscfg: Failed to load configuration %s\n", config_descs[i]->name); + cscfg_unload_owned_cfgs_feats(owner_info); goto exit_unlock; } config_descs[i]->load_owner = owner_info; @@ -422,6 +504,57 @@ int cscfg_load_config_sets(struct cscfg_config_desc **config_descs, } EXPORT_SYMBOL_GPL(cscfg_load_config_sets); +/** + * cscfg_unload_config_sets - unload a set of configurations by owner. + * + * Dynamic unload of configuration and feature sets is done on the basis of + * the load owner of that set. Later loaded configurations can depend on + * features loaded earlier. + * + * Therefore, unload is only possible if:- + * 1) no configurations are active. + * 2) the set being unloaded was the last to be loaded to maintain dependencies. + * + * @owner_info: Information on owner for set being unloaded. + */ +int cscfg_unload_config_sets(struct cscfg_load_owner_info *owner_info) +{ + int err = 0; + struct cscfg_load_owner_info *load_list_item = NULL; + + mutex_lock(&cscfg_mutex); + + /* cannot unload if anything is active */ + if (atomic_read(&cscfg_mgr->sys_active_cnt)) { + err = -EBUSY; + goto exit_unlock; + } + + /* cannot unload if not last loaded in load order */ + if (!list_empty(&cscfg_mgr->load_order_list)) { + load_list_item = list_last_entry(&cscfg_mgr->load_order_list, + struct cscfg_load_owner_info, item); + if (load_list_item != owner_info) + load_list_item = NULL; + } + + if (!load_list_item) { + err = -EINVAL; + goto exit_unlock; + } + + /* unload all belonging to load_owner */ + cscfg_unload_owned_cfgs_feats(owner_info); + + /* remove from load order list */ + list_del(&load_list_item->item); + +exit_unlock: + mutex_unlock(&cscfg_mutex); + return err; +} +EXPORT_SYMBOL_GPL(cscfg_unload_config_sets); + /* Handle coresight device registration and add configs and features to devices */ /* iterate through config lists and load matching configs to device */ diff --git a/drivers/hwtracing/coresight/coresight-syscfg.h b/drivers/hwtracing/coresight/coresight-syscfg.h index 08067e89edcf..e2b2bdab31aa 100644 --- a/drivers/hwtracing/coresight/coresight-syscfg.h +++ b/drivers/hwtracing/coresight/coresight-syscfg.h @@ -93,6 +93,7 @@ int cscfg_update_feat_param_val(struct cscfg_feature_desc *feat_desc, int cscfg_load_config_sets(struct cscfg_config_desc **cfg_descs, struct cscfg_feature_desc **feat_descs, struct cscfg_load_owner_info *owner_info); +int cscfg_unload_config_sets(struct cscfg_load_owner_info *owner_info); int cscfg_register_csdev(struct coresight_device *csdev, u32 match_flags, struct cscfg_csdev_feat_ops *ops); void cscfg_unregister_csdev(struct coresight_device *csdev); -- 2.17.1 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel