Message ID | 20220329091449.105308-1-kant@allwinnertech.com |
---|---|
State | New |
Headers | show |
Series | [RESEND] devfreq: governor: Save void *data in the governor userspace | expand |
On 3/29/2022 5:14 PM, Kant Fan wrote: > The member void *data in the structure devfreq can be overwrite > by governor_userspace. For example: > 1. The device driver assigned the devfreq governor to simple_ondemand > by the function devfreq_add_device() and init the devfreq member > void *data to a pointer of a static structure devfreq_simple_ondemand_data > by the function devfreq_add_device(). > 2. The user changed the devfreq governor to userspace by the command > "echo userspace > /sys/class/devfreq/.../governor". > 3. The governor userspace alloced a dynamic memory for the struct > userspace_data and assigend the member void *data of devfreq to > this memory by the function userspace_init(). > 4. The user changed the devfreq governor back to simple_ondemand > by the command "echo simple_ondemand > /sys/class/devfreq/.../governor". > 5. The governor userspace exited and assigned the member void *data > in the structure devfreq to NULL by the function userspace_exit(). > 6. The governor simple_ondemand fetched the static information of > devfreq_simple_ondemand_data in the function > devfreq_simple_ondemand_func() but the member void *data of devfreq was > assigned to NULL by the function userspace_exit(). > 7. The information of upthreshold and downdifferential is lost > and the governor simple_ondemand can't work correctly. > > The member void *data in the structure devfreq is designed for > a static pointer used in a governor and inited by the function > devfreq_add_device(). So if a governor want to use void *data > to do some other things, it must save void *data in the init() > function and restore void *data in the exit() function. > > Signed-off-by: Kant Fan <kant@allwinnertech.com> > --- > drivers/devfreq/governor_userspace.c | 6 +++++- > 1 file changed, 5 insertions(+), 1 deletion(-) > > diff --git a/drivers/devfreq/governor_userspace.c b/drivers/devfreq/governor_userspace.c > index ab9db7adb3ad..dbbb448dcbcf 100644 > --- a/drivers/devfreq/governor_userspace.c > +++ b/drivers/devfreq/governor_userspace.c > @@ -17,6 +17,7 @@ > struct userspace_data { > unsigned long user_frequency; > bool valid; > + void *saved_data; > }; > > static int devfreq_userspace_func(struct devfreq *df, unsigned long *freq) > @@ -91,6 +92,7 @@ static int userspace_init(struct devfreq *devfreq) > goto out; > } > data->valid = false; > + data->saved_data = devfreq->data; > devfreq->data = data; > > err = sysfs_create_group(&devfreq->dev.kobj, &dev_attr_group); > @@ -100,6 +102,8 @@ static int userspace_init(struct devfreq *devfreq) > > static void userspace_exit(struct devfreq *devfreq) > { > + struct userspace_data *data = devfreq->data; > + void *saved_data = data->saved_data; > /* > * Remove the sysfs entry, unless this is being called after > * device_del(), which should have done this already via kobject_del(). > @@ -108,7 +112,7 @@ static void userspace_exit(struct devfreq *devfreq) > sysfs_remove_group(&devfreq->dev.kobj, &dev_attr_group); > > kfree(devfreq->data); > - devfreq->data = NULL; > + devfreq->data = saved_data; > } > > static int devfreq_userspace_handler(struct devfreq *devfreq, Dear MyungJoo, Kyungmin & Chanwoo, Gently ping this issue... Does this patch has a chance to be accepted? This seems to be a bug in devfreq userspace governor, which affects the switching between governors -- When switching from userspace to ondemand, the ondemand governor would be invalid. If there's any question, please let me know. Thank you.
>On 3/29/2022 5:14 PM, Kant Fan wrote: >> The member void *data in the structure devfreq can be overwrite >> by governor_userspace. >> Signed-off-by: Kant Fan <kant@allwinnertech.com> >> --- >> drivers/devfreq/governor_userspace.c | 6 +++++- >> 1 file changed, 5 insertions(+), 1 deletion(-) >> >> diff --git a/drivers/devfreq/governor_userspace.c b/drivers/devfreq/governor_userspace.c >> index ab9db7adb3ad..dbbb448dcbcf 100644 >> --- a/drivers/devfreq/governor_userspace.c >> +++ b/drivers/devfreq/governor_userspace.c >> @@ -17,6 +17,7 @@ >> struct userspace_data { >> unsigned long user_frequency; >> bool valid; >> + void *saved_data; >> }; >> >> static int devfreq_userspace_func(struct devfreq *df, unsigned long *freq) >> @@ -91,6 +92,7 @@ static int userspace_init(struct devfreq *devfreq) >> goto out; >> } >> data->valid = false; >> + data->saved_data = devfreq->data; >> devfreq->data = data; >> >> err = sysfs_create_group(&devfreq->dev.kobj, &dev_attr_group); >> @@ -100,6 +102,8 @@ static int userspace_init(struct devfreq *devfreq) >> >> static void userspace_exit(struct devfreq *devfreq) >> { >> + struct userspace_data *data = devfreq->data; >> + void *saved_data = data->saved_data; >> /* >> * Remove the sysfs entry, unless this is being called after >> * device_del(), which should have done this already via kobject_del(). >> @@ -108,7 +112,7 @@ static void userspace_exit(struct devfreq *devfreq) >> sysfs_remove_group(&devfreq->dev.kobj, &dev_attr_group); >> >> kfree(devfreq->data); >> - devfreq->data = NULL; >> + devfreq->data = saved_data; >> } >> >> static int devfreq_userspace_handler(struct devfreq *devfreq, > >Dear MyungJoo, Kyungmin & Chanwoo, >Gently ping this issue... Does this patch has a chance to be accepted? >This seems to be a bug in devfreq userspace governor, which affects the >switching between governors -- When switching from userspace to >ondemand, the ondemand governor would be invalid. >If there's any question, please let me know. >Thank you. Yes, indeed. This is a bug. Actually, it appears that allocating a new memory buffer for devfreq->data itself is a bug for a governor, this is supposed to be allocated by a device driver. Thus, the comment of "void *data" of "struct devfreq" should be updated: "/* private data for governors given by device drivers */" It'd be better to have something like, "void *internal_data" for governors to freely handle within its context of init-exit, which is not touched by its users (device drivers). @Chanwoo: what's your opinion on this? Cheers, MyungJoo.
On 9/14/2022 5:43 PM, MyungJoo Ham wrote: >> On 3/29/2022 5:14 PM, Kant Fan wrote: >>> The member void *data in the structure devfreq can be overwrite >>> by governor_userspace. >>> Signed-off-by: Kant Fan <kant@allwinnertech.com> >>> --- >>> drivers/devfreq/governor_userspace.c | 6 +++++- >>> 1 file changed, 5 insertions(+), 1 deletion(-) >>> >>> diff --git a/drivers/devfreq/governor_userspace.c b/drivers/devfreq/governor_userspace.c >>> index ab9db7adb3ad..dbbb448dcbcf 100644 >>> --- a/drivers/devfreq/governor_userspace.c >>> +++ b/drivers/devfreq/governor_userspace.c >>> @@ -17,6 +17,7 @@ >>> struct userspace_data { >>> unsigned long user_frequency; >>> bool valid; >>> + void *saved_data; >>> }; >>> >>> static int devfreq_userspace_func(struct devfreq *df, unsigned long *freq) >>> @@ -91,6 +92,7 @@ static int userspace_init(struct devfreq *devfreq) >>> goto out; >>> } >>> data->valid = false; >>> + data->saved_data = devfreq->data; >>> devfreq->data = data; >>> >>> err = sysfs_create_group(&devfreq->dev.kobj, &dev_attr_group); >>> @@ -100,6 +102,8 @@ static int userspace_init(struct devfreq *devfreq) >>> >>> static void userspace_exit(struct devfreq *devfreq) >>> { >>> + struct userspace_data *data = devfreq->data; >>> + void *saved_data = data->saved_data; >>> /* >>> * Remove the sysfs entry, unless this is being called after >>> * device_del(), which should have done this already via kobject_del(). >>> @@ -108,7 +112,7 @@ static void userspace_exit(struct devfreq *devfreq) >>> sysfs_remove_group(&devfreq->dev.kobj, &dev_attr_group); >>> >>> kfree(devfreq->data); >>> - devfreq->data = NULL; >>> + devfreq->data = saved_data; >>> } >>> >>> static int devfreq_userspace_handler(struct devfreq *devfreq, >> >> Dear MyungJoo, Kyungmin & Chanwoo, >> Gently ping this issue... Does this patch has a chance to be accepted? >> This seems to be a bug in devfreq userspace governor, which affects the >> switching between governors -- When switching from userspace to >> ondemand, the ondemand governor would be invalid. >> If there's any question, please let me know. >> Thank you. > > Yes, indeed. This is a bug. > > Actually, it appears that allocating a new memory buffer for > devfreq->data itself is a bug for a governor, this is supposed > to be allocated by a device driver. Thus, the comment of > "void *data" of "struct devfreq" should be updated: > "/* private data for governors given by device drivers */" > > It'd be better to have something like, "void *internal_data" > for governors to freely handle within its context of init-exit, > which is not touched by its users (device drivers). > > @Chanwoo: what's your opinion on this? > > Cheers, > MyungJoo. > Hi MyungJoo, Thanks for your suggestion. Here's the patch-v2, please have a look: -- Subject: [PATCH] devfreq: governor: Add a private governor_data for governors in devfreq The member void *data in the structure devfreq can be overwrite by governor_userspace. For example: 1. The device driver assigned the devfreq governor to simple_ondemand by the function devfreq_add_device() and init the devfreq member void *data to a pointer of a static structure devfreq_simple_ondemand_data by the function devfreq_add_device(). 2. The user changed the devfreq governor to userspace by the command "echo userspace > /sys/class/devfreq/.../governor". 3. The governor userspace alloced a dynamic memory for the struct userspace_data and assigend the member void *data of devfreq to this memory by the function userspace_init(). 4. The user changed the devfreq governor back to simple_ondemand by the command "echo simple_ondemand > /sys/class/devfreq/.../governor". 5. The governor userspace exited and assigned the member void *data in the structure devfreq to NULL by the function userspace_exit(). 6. The governor simple_ondemand fetched the static information of devfreq_simple_ondemand_data in the function devfreq_simple_ondemand_func() but the member void *data of devfreq was assigned to NULL by the function userspace_exit(). 7. The information of upthreshold and downdifferential is lost and the governor simple_ondemand can't work correctly. The member void *data in the structure devfreq is designed for a static pointer used in a governor and inited by the function devfreq_add_device(). This patch add an element named governor_data in the devfreq structure which can be used by a governor(E.g userspace) who want to assign a private data to do some private things. Signed-off-by: Kant Fan <kant@allwinnertech.com> --- diff --git a/drivers/devfreq/governor_userspace.c b/drivers/devfreq/governor_userspace.c index ab9db7a..d69672c 100644 --- a/drivers/devfreq/governor_userspace.c +++ b/drivers/devfreq/governor_userspace.c @@ -21,7 +21,7 @@ static int devfreq_userspace_func(struct devfreq *df, unsigned long *freq) { - struct userspace_data *data = df->data; + struct userspace_data *data = df->governor_data; if (data->valid) *freq = data->user_frequency; @@ -40,7 +40,7 @@ int err = 0; mutex_lock(&devfreq->lock); - data = devfreq->data; + data = devfreq->governor_data; sscanf(buf, "%lu", &wanted); data->user_frequency = wanted; @@ -60,7 +60,7 @@ int err = 0; mutex_lock(&devfreq->lock); - data = devfreq->data; + data = devfreq->governor_data; if (data->valid) err = sprintf(buf, "%lu\n", data->user_frequency); @@ -91,7 +91,7 @@ goto out; } data->valid = false; - devfreq->data = data; + devfreq->governor_data = data; err = sysfs_create_group(&devfreq->dev.kobj, &dev_attr_group); out: @@ -107,8 +107,8 @@ if (devfreq->dev.kobj.sd) sysfs_remove_group(&devfreq->dev.kobj, &dev_attr_group); - kfree(devfreq->data); - devfreq->data = NULL; + kfree(devfreq->governor_data); + devfreq->governor_data = NULL; } static int devfreq_userspace_handler(struct devfreq *devfreq, diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h index 34aab4d..d265af3 100644 --- a/include/linux/devfreq.h +++ b/include/linux/devfreq.h @@ -152,8 +152,8 @@ * @max_state: count of entry present in the frequency table. * @previous_freq: previously configured frequency value. * @last_status: devfreq user device info, performance statistics - * @data: Private data of the governor. The devfreq framework does not - * touch this. + * @data: devfreq core pass to governors, governor should not change it. + * @governor_data: private data for governors, devfreq core doesn't touch it. * @user_min_freq_req: PM QoS minimum frequency request from user (via sysfs) * @user_max_freq_req: PM QoS maximum frequency request from user (via sysfs) * @scaling_min_freq: Limit minimum frequency requested by OPP interface @@ -193,7 +193,8 @@ unsigned long previous_freq; struct devfreq_dev_status last_status; - void *data; /* private data for governors */ + void *data; + void *governor_data; struct dev_pm_qos_request user_min_freq_req; struct dev_pm_qos_request user_max_freq_req;
On 9/15/2022 3:41 PM, Kant Fan wrote: >>>> static int devfreq_userspace_handler(struct devfreq *devfreq, >>> >>> Dear MyungJoo, Kyungmin & Chanwoo, >>> Gently ping this issue... Does this patch has a chance to be accepted? >>> This seems to be a bug in devfreq userspace governor, which affects the >>> switching between governors -- When switching from userspace to >>> ondemand, the ondemand governor would be invalid. >>> If there's any question, please let me know. >>> Thank you. >> >> Yes, indeed. This is a bug. >> >> Actually, it appears that allocating a new memory buffer for >> devfreq->data itself is a bug for a governor, this is supposed >> to be allocated by a device driver. Thus, the comment of >> "void *data" of "struct devfreq" should be updated: >> "/* private data for governors given by device drivers */" >> >> It'd be better to have something like, "void *internal_data" >> for governors to freely handle within its context of init-exit, >> which is not touched by its users (device drivers). >> >> @Chanwoo: what's your opinion on this? >> >> Cheers, >> MyungJoo. >> > > Hi MyungJoo, > Thanks for your suggestion. Here's the patch-v2, please have a look: > > -- > Subject: [PATCH] devfreq: governor: Add a private governor_data for > governors in devfreq > > The member void *data in the structure devfreq can be overwrite > by governor_userspace. For example: > 1. The device driver assigned the devfreq governor to simple_ondemand > by the function devfreq_add_device() and init the devfreq member > void *data to a pointer of a static structure devfreq_simple_ondemand_data > by the function devfreq_add_device(). > 2. The user changed the devfreq governor to userspace by the command > "echo userspace > /sys/class/devfreq/.../governor". > 3. The governor userspace alloced a dynamic memory for the struct > userspace_data and assigend the member void *data of devfreq to > this memory by the function userspace_init(). > 4. The user changed the devfreq governor back to simple_ondemand > by the command "echo simple_ondemand > /sys/class/devfreq/.../governor". > 5. The governor userspace exited and assigned the member void *data > in the structure devfreq to NULL by the function userspace_exit(). > 6. The governor simple_ondemand fetched the static information of > devfreq_simple_ondemand_data in the function > devfreq_simple_ondemand_func() but the member void *data of devfreq was > assigned to NULL by the function userspace_exit(). > 7. The information of upthreshold and downdifferential is lost > and the governor simple_ondemand can't work correctly. > > The member void *data in the structure devfreq is designed for > a static pointer used in a governor and inited by the function > devfreq_add_device(). This patch add an element named governor_data > in the devfreq structure which can be used by a governor(E.g userspace) > who want to assign a private data to do some private things. > > Signed-off-by: Kant Fan <kant@allwinnertech.com> > --- > > diff --git a/drivers/devfreq/governor_userspace.c > b/drivers/devfreq/governor_userspace.c > index ab9db7a..d69672c 100644 > --- a/drivers/devfreq/governor_userspace.c > +++ b/drivers/devfreq/governor_userspace.c > @@ -21,7 +21,7 @@ > > static int devfreq_userspace_func(struct devfreq *df, unsigned long > *freq) > { > - struct userspace_data *data = df->data; > + struct userspace_data *data = df->governor_data; > > if (data->valid) > *freq = data->user_frequency; > @@ -40,7 +40,7 @@ > int err = 0; > > mutex_lock(&devfreq->lock); > - data = devfreq->data; > + data = devfreq->governor_data; > > sscanf(buf, "%lu", &wanted); > data->user_frequency = wanted; > @@ -60,7 +60,7 @@ > int err = 0; > > mutex_lock(&devfreq->lock); > - data = devfreq->data; > + data = devfreq->governor_data; > > if (data->valid) > err = sprintf(buf, "%lu\n", data->user_frequency); > @@ -91,7 +91,7 @@ > goto out; > } > data->valid = false; > - devfreq->data = data; > + devfreq->governor_data = data; > > err = sysfs_create_group(&devfreq->dev.kobj, &dev_attr_group); > out: > @@ -107,8 +107,8 @@ > if (devfreq->dev.kobj.sd) > sysfs_remove_group(&devfreq->dev.kobj, &dev_attr_group); > > - kfree(devfreq->data); > - devfreq->data = NULL; > + kfree(devfreq->governor_data); > + devfreq->governor_data = NULL; > } > > static int devfreq_userspace_handler(struct devfreq *devfreq, > diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h > index 34aab4d..d265af3 100644 > --- a/include/linux/devfreq.h > +++ b/include/linux/devfreq.h > @@ -152,8 +152,8 @@ > * @max_state: count of entry present in the frequency table. > * @previous_freq: previously configured frequency value. > * @last_status: devfreq user device info, performance statistics > - * @data: Private data of the governor. The devfreq framework does not > - * touch this. > + * @data: devfreq core pass to governors, governor should not change > it. > + * @governor_data: private data for governors, devfreq core doesn't > touch it. > * @user_min_freq_req: PM QoS minimum frequency request from user > (via sysfs) > * @user_max_freq_req: PM QoS maximum frequency request from user > (via sysfs) > * @scaling_min_freq: Limit minimum frequency requested by OPP > interface > @@ -193,7 +193,8 @@ > unsigned long previous_freq; > struct devfreq_dev_status last_status; > > - void *data; /* private data for governors */ > + void *data; > + void *governor_data; > > struct dev_pm_qos_request user_min_freq_req; > struct dev_pm_qos_request user_max_freq_req; > Hi MyungJoo, Sorry to disturb. Just want to say that I'm looking forward to your advice on this patch. Thank you :>
> On 9/15/2022 3:41 PM, Kant Fan wrote: > > > > diff --git a/drivers/devfreq/governor_userspace.c > > b/drivers/devfreq/governor_userspace.c > > index ab9db7a..d69672c 100644 > > --- a/drivers/devfreq/governor_userspace.c > > +++ b/drivers/devfreq/governor_userspace.c > > @@ -21,7 +21,7 @@ > > > > static int devfreq_userspace_func(struct devfreq *df, unsigned long > > *freq) > > { > > - struct userspace_data *data = df->data; > > + struct userspace_data *data = df->governor_data; > > > > if (data->valid) > > *freq = data->user_frequency; > > @@ -40,7 +40,7 @@ > > int err = 0; > > > > mutex_lock(&devfreq->lock); > > - data = devfreq->data; > > + data = devfreq->governor_data; > > > > sscanf(buf, "%lu", &wanted); > > data->user_frequency = wanted; > > @@ -60,7 +60,7 @@ > > int err = 0; > > > > mutex_lock(&devfreq->lock); > > - data = devfreq->data; > > + data = devfreq->governor_data; > > > > if (data->valid) > > err = sprintf(buf, "%lu\n", data->user_frequency); > > @@ -91,7 +91,7 @@ > > goto out; > > } > > data->valid = false; > > - devfreq->data = data; > > + devfreq->governor_data = data; > > > > err = sysfs_create_group(&devfreq->dev.kobj, &dev_attr_group); > > out: > > @@ -107,8 +107,8 @@ > > if (devfreq->dev.kobj.sd) > > sysfs_remove_group(&devfreq->dev.kobj, &dev_attr_group); > > > > - kfree(devfreq->data); > > - devfreq->data = NULL; > > + kfree(devfreq->governor_data); > > + devfreq->governor_data = NULL; > > } > > > > static int devfreq_userspace_handler(struct devfreq *devfreq, > > diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h > > index 34aab4d..d265af3 100644 > > --- a/include/linux/devfreq.h > > +++ b/include/linux/devfreq.h > > @@ -152,8 +152,8 @@ > > * @max_state: count of entry present in the frequency table. > > * @previous_freq: previously configured frequency value. > > * @last_status: devfreq user device info, performance statistics > > - * @data: Private data of the governor. The devfreq framework does not > > - * touch this. > > + * @data: devfreq core pass to governors, governor should not change > > it. > > + * @governor_data: private data for governors, devfreq core doesn't > > touch it. > > * @user_min_freq_req: PM QoS minimum frequency request from user > > (via sysfs) > > * @user_max_freq_req: PM QoS maximum frequency request from user > > (via sysfs) > > * @scaling_min_freq: Limit minimum frequency requested by OPP > > interface > > @@ -193,7 +193,8 @@ > > unsigned long previous_freq; > > struct devfreq_dev_status last_status; > > > > - void *data; /* private data for governors */ > > + void *data; > > + void *governor_data; > > > > struct dev_pm_qos_request user_min_freq_req; > > struct dev_pm_qos_request user_max_freq_req; > > > > Hi MyungJoo, > Sorry to disturb. Just want to say that I'm looking forward to your > advice on this patch. Thank you :> > This new code looks good to me. Anyway, Chanwoo, how do you think of this? Acked-by: MyungJoo Ham <myungjoo.ham@samsung.com> Cheers, MyungJoo.
diff --git a/drivers/devfreq/governor_userspace.c b/drivers/devfreq/governor_userspace.c index ab9db7adb3ad..dbbb448dcbcf 100644 --- a/drivers/devfreq/governor_userspace.c +++ b/drivers/devfreq/governor_userspace.c @@ -17,6 +17,7 @@ struct userspace_data { unsigned long user_frequency; bool valid; + void *saved_data; }; static int devfreq_userspace_func(struct devfreq *df, unsigned long *freq) @@ -91,6 +92,7 @@ static int userspace_init(struct devfreq *devfreq) goto out; } data->valid = false; + data->saved_data = devfreq->data; devfreq->data = data; err = sysfs_create_group(&devfreq->dev.kobj, &dev_attr_group); @@ -100,6 +102,8 @@ static int userspace_init(struct devfreq *devfreq) static void userspace_exit(struct devfreq *devfreq) { + struct userspace_data *data = devfreq->data; + void *saved_data = data->saved_data; /* * Remove the sysfs entry, unless this is being called after * device_del(), which should have done this already via kobject_del(). @@ -108,7 +112,7 @@ static void userspace_exit(struct devfreq *devfreq) sysfs_remove_group(&devfreq->dev.kobj, &dev_attr_group); kfree(devfreq->data); - devfreq->data = NULL; + devfreq->data = saved_data; } static int devfreq_userspace_handler(struct devfreq *devfreq,
The member void *data in the structure devfreq can be overwrite by governor_userspace. For example: 1. The device driver assigned the devfreq governor to simple_ondemand by the function devfreq_add_device() and init the devfreq member void *data to a pointer of a static structure devfreq_simple_ondemand_data by the function devfreq_add_device(). 2. The user changed the devfreq governor to userspace by the command "echo userspace > /sys/class/devfreq/.../governor". 3. The governor userspace alloced a dynamic memory for the struct userspace_data and assigend the member void *data of devfreq to this memory by the function userspace_init(). 4. The user changed the devfreq governor back to simple_ondemand by the command "echo simple_ondemand > /sys/class/devfreq/.../governor". 5. The governor userspace exited and assigned the member void *data in the structure devfreq to NULL by the function userspace_exit(). 6. The governor simple_ondemand fetched the static information of devfreq_simple_ondemand_data in the function devfreq_simple_ondemand_func() but the member void *data of devfreq was assigned to NULL by the function userspace_exit(). 7. The information of upthreshold and downdifferential is lost and the governor simple_ondemand can't work correctly. The member void *data in the structure devfreq is designed for a static pointer used in a governor and inited by the function devfreq_add_device(). So if a governor want to use void *data to do some other things, it must save void *data in the init() function and restore void *data in the exit() function. Signed-off-by: Kant Fan <kant@allwinnertech.com> --- drivers/devfreq/governor_userspace.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)