cpufreq: Move to_gov_attr_set() to cpufreq.h
Subsystems (2)
PATCH 1/3 cpufreq: Move to_gov_attr_set() to cpufreq.h
So it can be reused by other codes.
--- drivers/cpufreq/cpufreq_governor_attr_set.c | 5 ----- include/linux/cpufreq.h | 5 +++++ 2 files changed, 5 insertions(+), 5 deletions(-)
drivers/cpufreq/cpufreq_governor_attr_set.c +0 -5
@@ -8,11 +8,6 @@#include "cpufreq_governor.h" -static inline struct gov_attr_set *to_gov_attr_set (struct kobject *kobj) -{ - return container_of(kobj, struct gov_attr_set, kobj); -} -static inline struct governor_attr *to_gov_attr (struct attribute *attr) { return container_of(attr, struct governor_attr, attr);
include/linux/cpufreq.h +5 -0
@@ -658,6 +658,11 @@ struct gov_attr_set {/* sysfs ops for cpufreq governors */ extern const struct sysfs_ops governor_sysfs_ops; +static inline struct gov_attr_set *to_gov_attr_set (struct kobject *kobj) +{ + return container_of(kobj, struct gov_attr_set, kobj); +} +void gov_attr_set_init (struct gov_attr_set *attr_set,struct list_head *list_node);void gov_attr_set_get (struct gov_attr_set *attr_set,struct list_head *list_node);unsigned int gov_attr_set_put (struct gov_attr_set *attr_set,struct list_head *list_node);
Signature · 1 line
2.31.1
PATCH 2/3 cpufreq: schedutil: Use to_gov_attr_set() to get the gov_attr_set
The to_gov_attr_set() has been moved to the cpufreq.h, so use it to get the gov_attr_set.
--- kernel/sched/cpufreq_schedutil.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/sched/cpufreq_schedutil.c +1 -1
@@ -539,7 +539,7 @@ ATTRIBUTE_GROUPS(sugov);static void sugov_tunables_free (struct kobject *kobj) { - struct gov_attr_set *attr_set = container_of(kobj, struct gov_attr_set, kobj); +struct gov_attr_set *attr_set =to_gov_attr_set (kobj);kfree (to_sugov_tunables (attr_set)); }
Signature · 1 line
2.31.1
PATCH 3/3 cpufreq: governor: Use kobject release() method to free dbs_data
In reply to Kevin HaoThe struct dbs_data embeds a struct gov_attr_set and
the struct gov_attr_set embeds a kobject. Since every kobject must have
a release() method and we can't use kfree() to free it directly,
so introduce cpufreq_dbs_data_release() to release the dbs_data via
the kobject::release() method. This fixes the calltrace like below:
ODEBUG: free active (active state 0) object type: timer_list hint: delayed_work_timer_fn+0x0/0x34
WARNING: CPU: 12 PID: 810 at lib/debugobjects.c:505 debug_print_object+0xb8/0x100 Modules linked in: CPU: 12 PID: 810 Comm: sh Not tainted 5.16.0-next-20220120-yocto-standard+ #536 Hardware name: Marvell OcteonTX CN96XX board (DT) pstate: 60400009 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : debug_print_object+0xb8/0x100 lr : debug_print_object+0xb8/0x100 sp : ffff80001dfcf9a0 x29: ffff80001dfcf9a0 x28: 0000000000000001 x27: ffff0001464f0000 x26: 0000000000000000 x25: ffff8000090e3f00 x24: ffff80000af60210 x23: ffff8000094dfb78 x22: ffff8000090e3f00 x21: ffff0001080b7118 x20: ffff80000aeb2430 x19: ffff800009e8f5e0 x18: 0000000000000000 x17: 0000000000000002 x16: 00004d62e58be040 x15: 013590470523aff8 x14: ffff8000090e1828 x13: 0000000001359047 x12: 00000000f5257d14 x11: 0000000000040591 x10: 0000000066c1ffea x9 : ffff8000080d15e0 x8 : ffff80000a1765a8 x7 : 0000000000000000 x6 : 0000000000000001 x5 : ffff800009e8c000 x4 : ffff800009e8c760 x3 : 0000000000000000 x2 : 0000000000000000 x1 : 0000000000000000 x0 : ffff0001474ed040 Call trace: debug_print_object+0xb8/0x100 __debug_check_no_obj_freed+0x1d0/0x25c debug_check_no_obj_freed+0x24/0xa0 kfree+0x11c/0x440 cpufreq_dbs_governor_exit+0xa8/0xac cpufreq_exit_governor+0x44/0x90 cpufreq_set_policy+0x29c/0x570 store_scaling_governor+0x110/0x154 store+0xb0/0xe0 sysfs_kf_write+0x58/0x84 kernfs_fop_write_iter+0x12c/0x1c0 new_sync_write+0xf0/0x18c vfs_write+0x1cc/0x220 ksys_write+0x74/0x100 __arm64_sys_write+0x28/0x3c invoke_syscall.constprop.0+0x58/0xf0 do_el0_svc+0x70/0x170 el0_svc+0x54/0x190 el0t_64_sync_handler+0xa4/0x130 el0t_64_sync+0x1a0/0x1a4 irq event stamp: 189006 hardirqs last enabled at (189005): [<ffff8000080849d0>] finish_task_switch.isra.0+0xe0/0x2c0 hardirqs last disabled at (189006): [<ffff8000090667a4>] el1_dbg+0x24/0xa0 softirqs last enabled at (188966): [<ffff8000080106d0>] __do_softirq+0x4b0/0x6a0 softirqs last disabled at (188957): [<ffff80000804a618>] __irq_exit_rcu+0x108/0x1a4
--- drivers/cpufreq/cpufreq_governor.c | 20 +++++++++++++------- drivers/cpufreq/cpufreq_governor.h | 1 + 2 files changed, 14 insertions(+), 7 deletions(-)
drivers/cpufreq/cpufreq_governor.c +13 -7
@@ -388,6 +388,15 @@ static void free_policy_dbs_info(struct policy_dbs_info *policy_dbs, gov->free (policy_dbs); } +static void cpufreq_dbs_data_release (struct kobject *kobj) +{ +struct dbs_data *dbs_data =to_dbs_data (to_gov_attr_set (kobj)); +struct dbs_governor *gov = dbs_data->gov; + + gov->exit (dbs_data); +kfree (dbs_data); +} +int cpufreq_dbs_governor_init (struct cpufreq_policy *policy) {struct dbs_governor *gov =dbs_governor_of (policy);
@@ -425,6 +434,7 @@ int cpufreq_dbs_governor_init(struct cpufreq_policy *policy) goto free_policy_dbs_info; } + dbs_data->gov = gov;gov_attr_set_init (&dbs_data->attr_set, &policy_dbs->list); ret = gov->init (dbs_data);
@@ -447,6 +457,7 @@ int cpufreq_dbs_governor_init(struct cpufreq_policy *policy) policy->governor_data = policy_dbs; gov->kobj_type.sysfs_ops = &governor_sysfs_ops; + gov->kobj_type.release = cpufreq_dbs_data_release; ret =kobject_init_and_add (&dbs_data->attr_set.kobj, &gov->kobj_type,get_governor_parent_kobj (policy),"%s" , gov->gov.name);
@@ -488,13 +499,8 @@ void cpufreq_dbs_governor_exit(struct cpufreq_policy *policy) policy->governor_data =NULL ; -if (!count) { -if (!have_governor_per_policy ()) - gov->gdbs_data =NULL ; - - gov->exit (dbs_data); -kfree (dbs_data); - } +if (!count && !have_governor_per_policy ()) + gov->gdbs_data =NULL ;free_policy_dbs_info (policy_dbs, gov);
drivers/cpufreq/cpufreq_governor.h +1 -0
@@ -37,6 +37,7 @@ enum {OD_NORMAL_SAMPLE, OD_SUB_SAMPLE};/* Governor demand based switching data (per-policy or global). */ struct dbs_data {struct gov_attr_set attr_set; +struct dbs_governor *gov;void *tuners;unsigned int ignore_nice_load;unsigned int sampling_rate;
Signature · 1 line
2.31.1
Rafael J. Wysocki
maintainerRe: [PATCH 3/3] cpufreq: governor: Use kobject release() method to free dbs_data
Quoted 96 lines · Kevin Hao
The struct
dbs_dataembeds a structgov_attr_setand
the structgov_attr_setembeds a kobject. Since every kobject must have
arelease()method and we can't usekfree()to free it directly,
so introducecpufreq_dbs_data_release()to release thedbs_datavia
thekobject::release()method. This fixes the calltrace like below:
ODEBUG: free active (active state 0) object type:timer_listhint:delayed_work_timer_fn+0x0/0x34WARNING: CPU: 12 PID: 810 at lib/debugobjects.c:505 debug_print_object+0xb8/0x100 Modules linked in: CPU: 12 PID: 810 Comm: sh Not tainted 5.16.0-next-20220120-yocto-standard+ #536 Hardware name: Marvell OcteonTX CN96XX board (DT) pstate: 60400009 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : debug_print_object+0xb8/0x100 lr : debug_print_object+0xb8/0x100 sp : ffff80001dfcf9a0 x29: ffff80001dfcf9a0 x28: 0000000000000001 x27: ffff0001464f0000 x26: 0000000000000000 x25: ffff8000090e3f00 x24: ffff80000af60210 x23: ffff8000094dfb78 x22: ffff8000090e3f00 x21: ffff0001080b7118 x20: ffff80000aeb2430 x19: ffff800009e8f5e0 x18: 0000000000000000 x17: 0000000000000002 x16: 00004d62e58be040 x15: 013590470523aff8 x14: ffff8000090e1828 x13: 0000000001359047 x12: 00000000f5257d14 x11: 0000000000040591 x10: 0000000066c1ffea x9 : ffff8000080d15e0 x8 : ffff80000a1765a8 x7 : 0000000000000000 x6 : 0000000000000001 x5 : ffff800009e8c000 x4 : ffff800009e8c760 x3 : 0000000000000000 x2 : 0000000000000000 x1 : 0000000000000000 x0 : ffff0001474ed040 Call trace: debug_print_object+0xb8/0x100 __debug_check_no_obj_freed+0x1d0/0x25c debug_check_no_obj_freed+0x24/0xa0 kfree+0x11c/0x440 cpufreq_dbs_governor_exit+0xa8/0xac cpufreq_exit_governor+0x44/0x90 cpufreq_set_policy+0x29c/0x570 store_scaling_governor+0x110/0x154 store+0xb0/0xe0 sysfs_kf_write+0x58/0x84 kernfs_fop_write_iter+0x12c/0x1c0 new_sync_write+0xf0/0x18c vfs_write+0x1cc/0x220 ksys_write+0x74/0x100 __arm64_sys_write+0x28/0x3c invoke_syscall.constprop.0+0x58/0xf0 do_el0_svc+0x70/0x170 el0_svc+0x54/0x190 el0t_64_sync_handler+0xa4/0x130 el0t_64_sync+0x1a0/0x1a4 irq event stamp: 189006 hardirqs last enabled at (189005): [<ffff8000080849d0>] finish_task_switch.isra.0+0xe0/0x2c0 hardirqs last disabled at (189006): [<ffff8000090667a4>] el1_dbg+0x24/0xa0 softirqs last enabled at (188966): [<ffff8000080106d0>] __do_softirq+0x4b0/0x6a0 softirqs last disabled at (188957): [<ffff80000804a618>] __irq_exit_rcu+0x108/0x1a4Fixes c4435630361d ("cpufreq: governor: New sysfs show/store callbacks for governor tunables")Signed-off-by Kevin Hao <[email protected]>--- drivers/cpufreq/cpufreq_governor.c | 20 +++++++++++++------- drivers/cpufreq/cpufreq_governor.h | 1 + 2 files changed, 14 insertions(+), 7 deletions(-)drivers/cpufreq/cpufreq_governor.c +11
-0@@ -388,6 +388,15 @@ static void free_policy_dbs_info(struct policy_dbs_info *policy_dbs, gov->free (policy_dbs); } +static void cpufreq_dbs_data_release (struct kobject *kobj) +{ +struct dbs_data *dbs_data =to_dbs_data (to_gov_attr_set (kobj)); +struct dbs_governor *gov = dbs_data->gov; + + gov->exit (dbs_data); +kfree (dbs_data); +} +int cpufreq_dbs_governor_init (struct cpufreq_policy *policy) {struct dbs_governor *gov =dbs_governor_of (policy);@@ -425,6 +434,7 @@ int cpufreq_dbs_governor_init(struct cpufreq_policy *policy) goto free_policy_dbs_info; } + dbs_data->gov = gov;gov_attr_set_init (&dbs_data->attr_set, &policy_dbs->list); ret = gov->init (dbs_data);@@ -447,6 +457,7 @@ int cpufreq_dbs_governor_init(struct cpufreq_policy *policy) policy->governor_data = policy_dbs; gov->kobj_type.sysfs_ops = &governor_sysfs_ops; + gov->kobj_type.release = cpufreq_dbs_data_release; ret =kobject_init_and_add (&dbs_data->attr_set.kobj, &gov->kobj_type,get_governor_parent_kobj (policy),"%s" , gov->gov.name);
drivers/cpufreq/cpufreq_governor.c void cpufreq_dbs_governor_exit(struct cpufreq_policy *policy) · line 495
Quoted 8 lines
drivers/cpufreq/cpufreq_governor.c +0
-5@@ -488,13 +499,8 @@ void cpufreq_dbs_governor_exit(struct cpufreq_policy *policy) policy->governor_data =NULL ; -if (!count) { -if (!have_governor_per_policy ()) - gov->gdbs_data =NULL ; - - gov->exit (dbs_data);
Good catch, but it is unclear to me why gov->exit() cannot be called from here.
Quoted 22 lines
drivers/cpufreq/cpufreq_governor.c +2
-2-kfree (dbs_data); - } +if (!count && !have_governor_per_policy ()) + gov->gdbs_data =NULL ;free_policy_dbs_info (policy_dbs, gov);drivers/cpufreq/cpufreq_governor.h +1
-1@@ -37,6 +37,7 @@ enum {OD_NORMAL_SAMPLE, OD_SUB_SAMPLE};/* Governor demand based switching data (per-policy or global). */ struct dbs_data {struct gov_attr_set attr_set; +struct dbs_governor *gov;void *tuners;unsigned int ignore_nice_load;unsigned int sampling_rate; --2.31.1
Re: [PATCH 3/3] cpufreq: governor: Use kobject release() method to free dbs_data
Quoted 100 lines · Rafael J. Wysocki
Quoted 99 lines · Kevin Hao
The struct
dbs_dataembeds a structgov_attr_setand
the structgov_attr_setembeds a kobject. Since every kobject must have
arelease()method and we can't usekfree()to free it directly,
so introducecpufreq_dbs_data_release()to release thedbs_datavia
thekobject::release()method. This fixes the calltrace like below:
ODEBUG: free active (active state 0) object type:timer_listhint:delayed_work_timer_fn+0x0/0x34WARNING: CPU: 12 PID: 810 at lib/debugobjects.c:505 debug_print_object+0xb8/0x100 Modules linked in: CPU: 12 PID: 810 Comm: sh Not tainted 5.16.0-next-20220120-yocto-standard+ #536 Hardware name: Marvell OcteonTX CN96XX board (DT) pstate: 60400009 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : debug_print_object+0xb8/0x100 lr : debug_print_object+0xb8/0x100 sp : ffff80001dfcf9a0 x29: ffff80001dfcf9a0 x28: 0000000000000001 x27: ffff0001464f0000 x26: 0000000000000000 x25: ffff8000090e3f00 x24: ffff80000af60210 x23: ffff8000094dfb78 x22: ffff8000090e3f00 x21: ffff0001080b7118 x20: ffff80000aeb2430 x19: ffff800009e8f5e0 x18: 0000000000000000 x17: 0000000000000002 x16: 00004d62e58be040 x15: 013590470523aff8 x14: ffff8000090e1828 x13: 0000000001359047 x12: 00000000f5257d14 x11: 0000000000040591 x10: 0000000066c1ffea x9 : ffff8000080d15e0 x8 : ffff80000a1765a8 x7 : 0000000000000000 x6 : 0000000000000001 x5 : ffff800009e8c000 x4 : ffff800009e8c760 x3 : 0000000000000000 x2 : 0000000000000000 x1 : 0000000000000000 x0 : ffff0001474ed040 Call trace: debug_print_object+0xb8/0x100 __debug_check_no_obj_freed+0x1d0/0x25c debug_check_no_obj_freed+0x24/0xa0 kfree+0x11c/0x440 cpufreq_dbs_governor_exit+0xa8/0xac cpufreq_exit_governor+0x44/0x90 cpufreq_set_policy+0x29c/0x570 store_scaling_governor+0x110/0x154 store+0xb0/0xe0 sysfs_kf_write+0x58/0x84 kernfs_fop_write_iter+0x12c/0x1c0 new_sync_write+0xf0/0x18c vfs_write+0x1cc/0x220 ksys_write+0x74/0x100 __arm64_sys_write+0x28/0x3c invoke_syscall.constprop.0+0x58/0xf0 do_el0_svc+0x70/0x170 el0_svc+0x54/0x190 el0t_64_sync_handler+0xa4/0x130 el0t_64_sync+0x1a0/0x1a4 irq event stamp: 189006 hardirqs last enabled at (189005): [<ffff8000080849d0>] finish_task_switch.isra.0+0xe0/0x2c0 hardirqs last disabled at (189006): [<ffff8000090667a4>] el1_dbg+0x24/0xa0 softirqs last enabled at (188966): [<ffff8000080106d0>] __do_softirq+0x4b0/0x6a0 softirqs last disabled at (188957): [<ffff80000804a618>] __irq_exit_rcu+0x108/0x1a4Fixes c4435630361d ("cpufreq: governor: New sysfs show/store callbacks for governor tunables")Signed-off-by Kevin Hao <[email protected]>--- drivers/cpufreq/cpufreq_governor.c | 20 +++++++++++++------- drivers/cpufreq/cpufreq_governor.h | 1 + 2 files changed, 14 insertions(+), 7 deletions(-)drivers/cpufreq/cpufreq_governor.c +11
-0@@ -388,6 +388,15 @@ static void free_policy_dbs_info(struct policy_dbs_info *policy_dbs, gov->free (policy_dbs); } +static void cpufreq_dbs_data_release (struct kobject *kobj) +{ +struct dbs_data *dbs_data =to_dbs_data (to_gov_attr_set (kobj)); +struct dbs_governor *gov = dbs_data->gov; + + gov->exit (dbs_data); +kfree (dbs_data); +} +int cpufreq_dbs_governor_init (struct cpufreq_policy *policy) {struct dbs_governor *gov =dbs_governor_of (policy);@@ -425,6 +434,7 @@ int cpufreq_dbs_governor_init(struct cpufreq_policy *policy) goto free_policy_dbs_info; } + dbs_data->gov = gov;gov_attr_set_init (&dbs_data->attr_set, &policy_dbs->list); ret = gov->init (dbs_data);@@ -447,6 +457,7 @@ int cpufreq_dbs_governor_init(struct cpufreq_policy *policy) policy->governor_data = policy_dbs; gov->kobj_type.sysfs_ops = &governor_sysfs_ops; + gov->kobj_type.release = cpufreq_dbs_data_release; ret =kobject_init_and_add (&dbs_data->attr_set.kobj, &gov->kobj_type,get_governor_parent_kobj (policy),"%s" , gov->gov.name);@@ -488,13 +499,8 @@ void cpufreq_dbs_governor_exit(struct cpufreq_policy *policy) policy->governor_data =NULL ;
Quoted 7 lines
drivers/cpufreq/cpufreq_governor.c void cpufreq_dbs_governor_exit(struct cpufreq_policy *policy) · line 495
Quoted 5 lines
drivers/cpufreq/cpufreq_governor.c +0
-5-if (!count) { -if (!have_governor_per_policy ()) - gov->gdbs_data =NULL ; - - gov->exit (dbs_data);Good catch, but it is unclear to me why
gov->exit()cannot be called from here.
The kobject_put(&attr_set->kobj) is invoked before this.
cpufreq_dbs_governor_exit()
gov_attr_set_put()
kobject_put(&attr_set->kobj)When the CONFIG_DEBUG_KOBJECT_RELEASE is not enabled, the invocation of kobject_put() would cause the dbs_data to be released immediately. So we have to move the gov->exit(dbs_data) before the release of dbs_data.
Thanks,
Kevin
Quoted 23 lines
Quoted 23 lines
drivers/cpufreq/cpufreq_governor.c +2
-2-kfree (dbs_data); - } +if (!count && !have_governor_per_policy ()) + gov->gdbs_data =NULL ;free_policy_dbs_info (policy_dbs, gov);drivers/cpufreq/cpufreq_governor.h +1
-1@@ -37,6 +37,7 @@ enum {OD_NORMAL_SAMPLE, OD_SUB_SAMPLE};/* Governor demand based switching data (per-policy or global). */ struct dbs_data {struct gov_attr_set attr_set; +struct dbs_governor *gov;void *tuners;unsigned int ignore_nice_load;unsigned int sampling_rate; --2.31.1
Re: [PATCH 3/3] cpufreq: governor: Use kobject release() method to free dbs_data
Quoted 109 lines · Kevin Hao
Quoted 100 lines · Rafael J. Wysocki
Quoted 99 lines · Kevin Hao
The struct
dbs_dataembeds a structgov_attr_setand
the structgov_attr_setembeds a kobject. Since every kobject must have
arelease()method and we can't usekfree()to free it directly,
so introducecpufreq_dbs_data_release()to release thedbs_datavia
thekobject::release()method. This fixes the calltrace like below:
ODEBUG: free active (active state 0) object type:timer_listhint:delayed_work_timer_fn+0x0/0x34WARNING: CPU: 12 PID: 810 at lib/debugobjects.c:505 debug_print_object+0xb8/0x100 Modules linked in: CPU: 12 PID: 810 Comm: sh Not tainted 5.16.0-next-20220120-yocto-standard+ #536 Hardware name: Marvell OcteonTX CN96XX board (DT) pstate: 60400009 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : debug_print_object+0xb8/0x100 lr : debug_print_object+0xb8/0x100 sp : ffff80001dfcf9a0 x29: ffff80001dfcf9a0 x28: 0000000000000001 x27: ffff0001464f0000 x26: 0000000000000000 x25: ffff8000090e3f00 x24: ffff80000af60210 x23: ffff8000094dfb78 x22: ffff8000090e3f00 x21: ffff0001080b7118 x20: ffff80000aeb2430 x19: ffff800009e8f5e0 x18: 0000000000000000 x17: 0000000000000002 x16: 00004d62e58be040 x15: 013590470523aff8 x14: ffff8000090e1828 x13: 0000000001359047 x12: 00000000f5257d14 x11: 0000000000040591 x10: 0000000066c1ffea x9 : ffff8000080d15e0 x8 : ffff80000a1765a8 x7 : 0000000000000000 x6 : 0000000000000001 x5 : ffff800009e8c000 x4 : ffff800009e8c760 x3 : 0000000000000000 x2 : 0000000000000000 x1 : 0000000000000000 x0 : ffff0001474ed040 Call trace: debug_print_object+0xb8/0x100 __debug_check_no_obj_freed+0x1d0/0x25c debug_check_no_obj_freed+0x24/0xa0 kfree+0x11c/0x440 cpufreq_dbs_governor_exit+0xa8/0xac cpufreq_exit_governor+0x44/0x90 cpufreq_set_policy+0x29c/0x570 store_scaling_governor+0x110/0x154 store+0xb0/0xe0 sysfs_kf_write+0x58/0x84 kernfs_fop_write_iter+0x12c/0x1c0 new_sync_write+0xf0/0x18c vfs_write+0x1cc/0x220 ksys_write+0x74/0x100 __arm64_sys_write+0x28/0x3c invoke_syscall.constprop.0+0x58/0xf0 do_el0_svc+0x70/0x170 el0_svc+0x54/0x190 el0t_64_sync_handler+0xa4/0x130 el0t_64_sync+0x1a0/0x1a4 irq event stamp: 189006 hardirqs last enabled at (189005): [<ffff8000080849d0>] finish_task_switch.isra.0+0xe0/0x2c0 hardirqs last disabled at (189006): [<ffff8000090667a4>] el1_dbg+0x24/0xa0 softirqs last enabled at (188966): [<ffff8000080106d0>] __do_softirq+0x4b0/0x6a0 softirqs last disabled at (188957): [<ffff80000804a618>] __irq_exit_rcu+0x108/0x1a4Fixes c4435630361d ("cpufreq: governor: New sysfs show/store callbacks for governor tunables")Signed-off-by Kevin Hao <[email protected]>--- drivers/cpufreq/cpufreq_governor.c | 20 +++++++++++++------- drivers/cpufreq/cpufreq_governor.h | 1 + 2 files changed, 14 insertions(+), 7 deletions(-)drivers/cpufreq/cpufreq_governor.c +11
-0@@ -388,6 +388,15 @@ static void free_policy_dbs_info(struct policy_dbs_info *policy_dbs, gov->free (policy_dbs); } +static void cpufreq_dbs_data_release (struct kobject *kobj) +{ +struct dbs_data *dbs_data =to_dbs_data (to_gov_attr_set (kobj)); +struct dbs_governor *gov = dbs_data->gov; + + gov->exit (dbs_data); +kfree (dbs_data); +} +int cpufreq_dbs_governor_init (struct cpufreq_policy *policy) {struct dbs_governor *gov =dbs_governor_of (policy);@@ -425,6 +434,7 @@ int cpufreq_dbs_governor_init(struct cpufreq_policy *policy) goto free_policy_dbs_info; } + dbs_data->gov = gov;gov_attr_set_init (&dbs_data->attr_set, &policy_dbs->list); ret = gov->init (dbs_data);@@ -447,6 +457,7 @@ int cpufreq_dbs_governor_init(struct cpufreq_policy *policy) policy->governor_data = policy_dbs; gov->kobj_type.sysfs_ops = &governor_sysfs_ops; + gov->kobj_type.release = cpufreq_dbs_data_release; ret =kobject_init_and_add (&dbs_data->attr_set.kobj, &gov->kobj_type,get_governor_parent_kobj (policy),"%s" , gov->gov.name);@@ -488,13 +499,8 @@ void cpufreq_dbs_governor_exit(struct cpufreq_policy *policy) policy->governor_data =NULL ;Quoted 7 lines
drivers/cpufreq/cpufreq_governor.c void cpufreq_dbs_governor_exit(struct cpufreq_policy *policy) · line 495
Quoted 5 lines
drivers/cpufreq/cpufreq_governor.c +0
-5-if (!count) { -if (!have_governor_per_policy ()) - gov->gdbs_data =NULL ; - - gov->exit (dbs_data);Good catch, but it is unclear to me why
gov->exit()cannot be called from here.
Quoted 8 lines
The
kobject_put(&attr_set->kobj)is invoked before this.
cpufreq_dbs_governor_exit()gov_attr_set_put() kobject_put(&attr_set->kobj)When the
CONFIG_DEBUG_KOBJECT_RELEASEis not enabled, the invocation ofkobject_put()would cause thedbs_datato be released immediately. So we have to move thegov->exit(dbs_data)before the release ofdbs_data.
Ping.
Thanks,
Kevin
Quoted 27 lines
Thanks,
KevinQuoted 23 lines
Quoted 23 lines
drivers/cpufreq/cpufreq_governor.c +2
-2-kfree (dbs_data); - } +if (!count && !have_governor_per_policy ()) + gov->gdbs_data =NULL ;free_policy_dbs_info (policy_dbs, gov);drivers/cpufreq/cpufreq_governor.h +1
-1@@ -37,6 +37,7 @@ enum {OD_NORMAL_SAMPLE, OD_SUB_SAMPLE};/* Governor demand based switching data (per-policy or global). */ struct dbs_data {struct gov_attr_set attr_set; +struct dbs_governor *gov;void *tuners;unsigned int ignore_nice_load;unsigned int sampling_rate; --2.31.1
Rafael J. Wysocki
maintainerRe: [PATCH 3/3] cpufreq: governor: Use kobject release() method to free dbs_data
Quoted 111 lines · Kevin Hao
Quoted 109 lines · Kevin Hao
Quoted 107 lines · Rafael J. Wysocki
Quoted 96 lines · Kevin Hao
The struct
dbs_dataembeds a structgov_attr_setand
the structgov_attr_setembeds a kobject. Since every kobject must have
arelease()method and we can't usekfree()to free it directly,
so introducecpufreq_dbs_data_release()to release thedbs_datavia
thekobject::release()method. This fixes the calltrace like below:
ODEBUG: free active (active state 0) object type:timer_listhint:delayed_work_timer_fn+0x0/0x34WARNING: CPU: 12 PID: 810 at lib/debugobjects.c:505 debug_print_object+0xb8/0x100 Modules linked in: CPU: 12 PID: 810 Comm: sh Not tainted 5.16.0-next-20220120-yocto-standard+ #536 Hardware name: Marvell OcteonTX CN96XX board (DT) pstate: 60400009 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : debug_print_object+0xb8/0x100 lr : debug_print_object+0xb8/0x100 sp : ffff80001dfcf9a0 x29: ffff80001dfcf9a0 x28: 0000000000000001 x27: ffff0001464f0000 x26: 0000000000000000 x25: ffff8000090e3f00 x24: ffff80000af60210 x23: ffff8000094dfb78 x22: ffff8000090e3f00 x21: ffff0001080b7118 x20: ffff80000aeb2430 x19: ffff800009e8f5e0 x18: 0000000000000000 x17: 0000000000000002 x16: 00004d62e58be040 x15: 013590470523aff8 x14: ffff8000090e1828 x13: 0000000001359047 x12: 00000000f5257d14 x11: 0000000000040591 x10: 0000000066c1ffea x9 : ffff8000080d15e0 x8 : ffff80000a1765a8 x7 : 0000000000000000 x6 : 0000000000000001 x5 : ffff800009e8c000 x4 : ffff800009e8c760 x3 : 0000000000000000 x2 : 0000000000000000 x1 : 0000000000000000 x0 : ffff0001474ed040 Call trace: debug_print_object+0xb8/0x100 __debug_check_no_obj_freed+0x1d0/0x25c debug_check_no_obj_freed+0x24/0xa0 kfree+0x11c/0x440 cpufreq_dbs_governor_exit+0xa8/0xac cpufreq_exit_governor+0x44/0x90 cpufreq_set_policy+0x29c/0x570 store_scaling_governor+0x110/0x154 store+0xb0/0xe0 sysfs_kf_write+0x58/0x84 kernfs_fop_write_iter+0x12c/0x1c0 new_sync_write+0xf0/0x18c vfs_write+0x1cc/0x220 ksys_write+0x74/0x100 __arm64_sys_write+0x28/0x3c invoke_syscall.constprop.0+0x58/0xf0 do_el0_svc+0x70/0x170 el0_svc+0x54/0x190 el0t_64_sync_handler+0xa4/0x130 el0t_64_sync+0x1a0/0x1a4 irq event stamp: 189006 hardirqs last enabled at (189005): [<ffff8000080849d0>] finish_task_switch.isra.0+0xe0/0x2c0 hardirqs last disabled at (189006): [<ffff8000090667a4>] el1_dbg+0x24/0xa0 softirqs last enabled at (188966): [<ffff8000080106d0>] __do_softirq+0x4b0/0x6a0 softirqs last disabled at (188957): [<ffff80000804a618>] __irq_exit_rcu+0x108/0x1a4Fixes c4435630361d ("cpufreq: governor: New sysfs show/store callbacks for governor tunables")Signed-off-by Kevin Hao <[email protected]>--- drivers/cpufreq/cpufreq_governor.c | 20 +++++++++++++------- drivers/cpufreq/cpufreq_governor.h | 1 + 2 files changed, 14 insertions(+), 7 deletions(-)drivers/cpufreq/cpufreq_governor.c +11
-0@@ -388,6 +388,15 @@ static void free_policy_dbs_info(struct policy_dbs_info *policy_dbs, gov->free (policy_dbs); } +static void cpufreq_dbs_data_release (struct kobject *kobj) +{ +struct dbs_data *dbs_data =to_dbs_data (to_gov_attr_set (kobj)); +struct dbs_governor *gov = dbs_data->gov; + + gov->exit (dbs_data); +kfree (dbs_data); +} +int cpufreq_dbs_governor_init (struct cpufreq_policy *policy) {struct dbs_governor *gov =dbs_governor_of (policy);@@ -425,6 +434,7 @@ int cpufreq_dbs_governor_init(struct cpufreq_policy *policy) goto free_policy_dbs_info; } + dbs_data->gov = gov;gov_attr_set_init (&dbs_data->attr_set, &policy_dbs->list); ret = gov->init (dbs_data);@@ -447,6 +457,7 @@ int cpufreq_dbs_governor_init(struct cpufreq_policy *policy) policy->governor_data = policy_dbs; gov->kobj_type.sysfs_ops = &governor_sysfs_ops; + gov->kobj_type.release = cpufreq_dbs_data_release; ret =kobject_init_and_add (&dbs_data->attr_set.kobj, &gov->kobj_type,get_governor_parent_kobj (policy),"%s" , gov->gov.name);drivers/cpufreq/cpufreq_governor.c void cpufreq_dbs_governor_exit(struct cpufreq_policy *policy) · line 495
Quoted 8 lines
drivers/cpufreq/cpufreq_governor.c +0
-5@@ -488,13 +499,8 @@ void cpufreq_dbs_governor_exit(struct cpufreq_policy *policy) policy->governor_data =NULL ; -if (!count) { -if (!have_governor_per_policy ()) - gov->gdbs_data =NULL ; - - gov->exit (dbs_data);Good catch, but it is unclear to me why
gov->exit()cannot be called from here.
Quoted 8 lines
Quoted 8 lines
The
kobject_put(&attr_set->kobj)is invoked before this.
cpufreq_dbs_governor_exit()gov_attr_set_put() kobject_put(&attr_set->kobj)When the
CONFIG_DEBUG_KOBJECT_RELEASEis not enabled, the invocation ofkobject_put()would cause thedbs_datato be released immediately. So we have to move thegov->exit(dbs_data)before the release ofdbs_data.
I see, but the changelog is missing this information, so I've added the following paragraph to it:
Because dbs_data can be freed by the gov_attr_set_put() call in cpufreq_dbs_governor_exit() now, it is also necessary to put the invocation of the governor ->exit() callback into the new cpufreq_dbs_data_release() function.
and queued it up for 5.19.
Thanks!
Rafael J. Wysocki
maintainerQuoted 32 lines · Kevin Hao
So it can be reused by other codes.
Signed-off-by Kevin Hao <[email protected]>--- drivers/cpufreq/cpufreq_governor_attr_set.c | 5 ----- include/linux/cpufreq.h | 5 +++++ 2 files changed, 5 insertions(+), 5 deletions(-)drivers/cpufreq/cpufreq_governor_attr_set.c +0
-5@@ -8,11 +8,6 @@#include "cpufreq_governor.h" -static inline struct gov_attr_set *to_gov_attr_set (struct kobject *kobj) -{ - return container_of(kobj, struct gov_attr_set, kobj); -} -static inline struct governor_attr *to_gov_attr (struct attribute *attr) { return container_of(attr, struct governor_attr, attr);include/linux/cpufreq.h +0
-0@@ -658,6 +658,11 @@ struct gov_attr_set {/* sysfs ops for cpufreq governors */ extern const struct sysfs_ops governor_sysfs_ops;
include/linux/cpufreq.h struct gov_attr_set {
Quoted 10 lines
include/linux/cpufreq.h +5
-1+static inline struct gov_attr_set *to_gov_attr_set (struct kobject *kobj) +{ + return container_of(kobj, struct gov_attr_set, kobj); +} +void gov_attr_set_init (struct gov_attr_set *attr_set,struct list_head *list_node);void gov_attr_set_get (struct gov_attr_set *attr_set,struct list_head *list_node);unsigned int gov_attr_set_put (struct gov_attr_set *attr_set,struct list_head *list_node); --
This one and the [2/3] have been applied as 5.18 material.
I've replied to the [3/3] directly.
Thanks!