From eb2ec49606c2a02d6382d56a0e19f34e515fde3f Mon Sep 17 00:00:00 2001 From: Mike Leach Date: Wed, 24 Nov 2021 20:00:35 +0000 Subject: coresight: syscfg: Update load API for config loadable modules CoreSight configurations and features can be added as kernel loadable modules. This patch updates the load owner API to ensure that the module cannot be unloaded either: 1) if the config it supplies is in use 2) if the module is not the last in the load order list. Signed-off-by: Mike Leach Link: https://lore.kernel.org/r/20211124200038.28662-4-mike.leach@linaro.org Signed-off-by: Mathieu Poirier --- drivers/hwtracing/coresight/coresight-syscfg.c | 39 +++++++++++++++++++++++++- drivers/hwtracing/coresight/coresight-syscfg.h | 1 + 2 files changed, 39 insertions(+), 1 deletion(-) (limited to 'drivers/hwtracing') diff --git a/drivers/hwtracing/coresight/coresight-syscfg.c b/drivers/hwtracing/coresight/coresight-syscfg.c index 8bff7da1aab2..678ee8250d85 100644 --- a/drivers/hwtracing/coresight/coresight-syscfg.c +++ b/drivers/hwtracing/coresight/coresight-syscfg.c @@ -368,6 +368,26 @@ unlock_exit: return err; } +/* + * Conditionally up reference count on owner to prevent unload. + * + * module loaded configs need to be locked in to prevent premature unload. + */ +static int cscfg_owner_get(struct cscfg_load_owner_info *owner_info) +{ + if ((owner_info->type == CSCFG_OWNER_MODULE) && + (!try_module_get(owner_info->owner_handle))) + return -EINVAL; + return 0; +} + +/* conditionally lower ref count on an owner */ +static void cscfg_owner_put(struct cscfg_load_owner_info *owner_info) +{ + if (owner_info->type == CSCFG_OWNER_MODULE) + module_put(owner_info->owner_handle); +} + static void cscfg_remove_owned_csdev_configs(struct coresight_device *csdev, void *load_owner) { struct cscfg_config_csdev *config_csdev, *tmp; @@ -497,6 +517,14 @@ int cscfg_load_config_sets(struct cscfg_config_desc **config_descs, /* add the load owner to the load order list */ list_add_tail(&owner_info->item, &cscfg_mgr->load_order_list); + if (!list_is_singular(&cscfg_mgr->load_order_list)) { + /* lock previous item in load order list */ + err = cscfg_owner_get(list_prev_entry(owner_info, item)); + if (err) { + cscfg_unload_owned_cfgs_feats(owner_info); + list_del(&owner_info->item); + } + } exit_unlock: mutex_unlock(&cscfg_mutex); @@ -547,7 +575,11 @@ int cscfg_unload_config_sets(struct cscfg_load_owner_info *owner_info) cscfg_unload_owned_cfgs_feats(owner_info); /* remove from load order list */ - list_del(&load_list_item->item); + if (!list_is_singular(&cscfg_mgr->load_order_list)) { + /* unlock previous item in load order list */ + cscfg_owner_put(list_prev_entry(owner_info, item)); + } + list_del(&owner_info->item); exit_unlock: mutex_unlock(&cscfg_mutex); @@ -739,6 +771,10 @@ int cscfg_activate_config(unsigned long cfg_hash) list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) { if ((unsigned long)config_desc->event_ea->var == cfg_hash) { + /* must ensure that config cannot be unloaded in use */ + err = cscfg_owner_get(config_desc->load_owner); + if (err) + break; /* * increment the global active count - control changes to * active configurations @@ -779,6 +815,7 @@ void cscfg_deactivate_config(unsigned long cfg_hash) if ((unsigned long)config_desc->event_ea->var == cfg_hash) { atomic_dec(&config_desc->active_cnt); atomic_dec(&cscfg_mgr->sys_active_cnt); + cscfg_owner_put(config_desc->load_owner); dev_dbg(cscfg_device(), "Deactivate config %s.\n", config_desc->name); break; } diff --git a/drivers/hwtracing/coresight/coresight-syscfg.h b/drivers/hwtracing/coresight/coresight-syscfg.h index e2b2bdab31aa..1da37874f70f 100644 --- a/drivers/hwtracing/coresight/coresight-syscfg.h +++ b/drivers/hwtracing/coresight/coresight-syscfg.h @@ -61,6 +61,7 @@ struct cscfg_registered_csdev { /* owner types for loading and unloading of config and feature sets */ enum cscfg_load_owner_type { CSCFG_OWNER_PRELOAD, + CSCFG_OWNER_MODULE, }; /** -- cgit v1.2.3