powercap/dtpm: Destroy hierarchy function

The hierarchy creation function exits but without a destroy hierarchy
function. Due to that, the modules creating the hierarchy can not be
unloaded properly because they don't have an exit callback.

Provide the dtpm_destroy_hierarchy() function to remove the previously
created hierarchy.

The function relies on all the release mechanisms implemented by the
underlying powercap framework.

Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
Link: https://lore.kernel.org/r/20220130210210.549877-4-daniel.lezcano@linaro.org
This commit is contained in:
Daniel Lezcano 2022-01-30 22:02:06 +01:00
parent 690de0b401
commit c404c64d64
2 changed files with 46 additions and 0 deletions

View file

@ -617,3 +617,46 @@ int dtpm_create_hierarchy(struct of_device_id *dtpm_match_table)
return ret;
}
EXPORT_SYMBOL_GPL(dtpm_create_hierarchy);
static void __dtpm_destroy_hierarchy(struct dtpm *dtpm)
{
struct dtpm *child, *aux;
list_for_each_entry_safe(child, aux, &dtpm->children, sibling)
__dtpm_destroy_hierarchy(child);
/*
* At this point, we know all children were removed from the
* recursive call before
*/
dtpm_unregister(dtpm);
}
void dtpm_destroy_hierarchy(void)
{
int i;
mutex_lock(&dtpm_lock);
if (!pct)
goto out_unlock;
__dtpm_destroy_hierarchy(root);
for (i = 0; i < ARRAY_SIZE(dtpm_subsys); i++) {
if (!dtpm_subsys[i]->exit)
continue;
dtpm_subsys[i]->exit();
}
powercap_unregister_control_type(pct);
pct = NULL;
out_unlock:
mutex_unlock(&dtpm_lock);
}
EXPORT_SYMBOL_GPL(dtpm_destroy_hierarchy);

View file

@ -37,6 +37,7 @@ struct device_node;
struct dtpm_subsys_ops {
const char *name;
int (*init)(void);
void (*exit)(void);
int (*setup)(struct dtpm *, struct device_node *);
};
@ -67,4 +68,6 @@ void dtpm_unregister(struct dtpm *dtpm);
int dtpm_register(const char *name, struct dtpm *dtpm, struct dtpm *parent);
int dtpm_create_hierarchy(struct of_device_id *dtpm_match_table);
void dtpm_destroy_hierarchy(void);
#endif