Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <mike.leach@linaro.org>
Link: https://lore.kernel.org/r/20211124200038.28662-4-mike.leach@linaro.org
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>

authored by

Mike Leach and committed by
Mathieu Poirier
eb2ec496 02bd588e

+39 -1
+38 -1
drivers/hwtracing/coresight/coresight-syscfg.c
··· 368 368 return err; 369 369 } 370 370 371 + /* 372 + * Conditionally up reference count on owner to prevent unload. 373 + * 374 + * module loaded configs need to be locked in to prevent premature unload. 375 + */ 376 + static int cscfg_owner_get(struct cscfg_load_owner_info *owner_info) 377 + { 378 + if ((owner_info->type == CSCFG_OWNER_MODULE) && 379 + (!try_module_get(owner_info->owner_handle))) 380 + return -EINVAL; 381 + return 0; 382 + } 383 + 384 + /* conditionally lower ref count on an owner */ 385 + static void cscfg_owner_put(struct cscfg_load_owner_info *owner_info) 386 + { 387 + if (owner_info->type == CSCFG_OWNER_MODULE) 388 + module_put(owner_info->owner_handle); 389 + } 390 + 371 391 static void cscfg_remove_owned_csdev_configs(struct coresight_device *csdev, void *load_owner) 372 392 { 373 393 struct cscfg_config_csdev *config_csdev, *tmp; ··· 517 497 518 498 /* add the load owner to the load order list */ 519 499 list_add_tail(&owner_info->item, &cscfg_mgr->load_order_list); 500 + if (!list_is_singular(&cscfg_mgr->load_order_list)) { 501 + /* lock previous item in load order list */ 502 + err = cscfg_owner_get(list_prev_entry(owner_info, item)); 503 + if (err) { 504 + cscfg_unload_owned_cfgs_feats(owner_info); 505 + list_del(&owner_info->item); 506 + } 507 + } 520 508 521 509 exit_unlock: 522 510 mutex_unlock(&cscfg_mutex); ··· 575 547 cscfg_unload_owned_cfgs_feats(owner_info); 576 548 577 549 /* remove from load order list */ 578 - list_del(&load_list_item->item); 550 + if (!list_is_singular(&cscfg_mgr->load_order_list)) { 551 + /* unlock previous item in load order list */ 552 + cscfg_owner_put(list_prev_entry(owner_info, item)); 553 + } 554 + list_del(&owner_info->item); 579 555 580 556 exit_unlock: 581 557 mutex_unlock(&cscfg_mutex); ··· 771 739 772 740 list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) { 773 741 if ((unsigned long)config_desc->event_ea->var == cfg_hash) { 742 + /* must ensure that config cannot be unloaded in use */ 743 + err = cscfg_owner_get(config_desc->load_owner); 744 + if (err) 745 + break; 774 746 /* 775 747 * increment the global active count - control changes to 776 748 * active configurations ··· 815 779 if ((unsigned long)config_desc->event_ea->var == cfg_hash) { 816 780 atomic_dec(&config_desc->active_cnt); 817 781 atomic_dec(&cscfg_mgr->sys_active_cnt); 782 + cscfg_owner_put(config_desc->load_owner); 818 783 dev_dbg(cscfg_device(), "Deactivate config %s.\n", config_desc->name); 819 784 break; 820 785 }
+1
drivers/hwtracing/coresight/coresight-syscfg.h
··· 61 61 /* owner types for loading and unloading of config and feature sets */ 62 62 enum cscfg_load_owner_type { 63 63 CSCFG_OWNER_PRELOAD, 64 + CSCFG_OWNER_MODULE, 64 65 }; 65 66 66 67 /**