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:
parent
690de0b401
commit
c404c64d64
@ -617,3 +617,46 @@ out_unlock:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(dtpm_create_hierarchy);
|
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);
|
||||||
|
@ -37,6 +37,7 @@ struct device_node;
|
|||||||
struct dtpm_subsys_ops {
|
struct dtpm_subsys_ops {
|
||||||
const char *name;
|
const char *name;
|
||||||
int (*init)(void);
|
int (*init)(void);
|
||||||
|
void (*exit)(void);
|
||||||
int (*setup)(struct dtpm *, struct device_node *);
|
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_register(const char *name, struct dtpm *dtpm, struct dtpm *parent);
|
||||||
|
|
||||||
int dtpm_create_hierarchy(struct of_device_id *dtpm_match_table);
|
int dtpm_create_hierarchy(struct of_device_id *dtpm_match_table);
|
||||||
|
|
||||||
|
void dtpm_destroy_hierarchy(void);
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user