* [dpdk-dev] [PATCH 1/2] power: switching to unbuffered stdio for /sys file access @ 2017-10-16 13:47 Radoslaw Biernacki 2017-10-16 13:47 ` [dpdk-dev] [PATCH 2/2] power: check if userspace governor is available Radoslaw Biernacki ` (3 more replies) 0 siblings, 4 replies; 15+ messages in thread From: Radoslaw Biernacki @ 2017-10-16 13:47 UTC (permalink / raw) To: dev, david.hunt; +Cc: stable, alan.carew, pablo.de.lara.guarch This patch fixes the bug caused by improper use of buffered stdio file access for switching the CPU frequency and governor. Each write operation when using buffered stdio must be flushed out and the return code from fflush() must be verified. In buffered mode, write() syscall return value is is not returned by fwrite()/fputs()/fprintf(). Since with buffered approatch, fflush() need to be done every time it is better to use unbuffered mode or not use stdio at all (instead use plain open/write functions). To minimize amount of changes this fix use first approach. Signed-off-by: Radoslaw Biernacki <radoslaw.biernacki@linaro.org> --- lib/librte_power/rte_power_acpi_cpufreq.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/librte_power/rte_power_acpi_cpufreq.c b/lib/librte_power/rte_power_acpi_cpufreq.c index 01ac5ac..8bf5685 100644 --- a/lib/librte_power/rte_power_acpi_cpufreq.c +++ b/lib/librte_power/rte_power_acpi_cpufreq.c @@ -143,12 +143,13 @@ set_freq_internal(struct rte_power_info *pi, uint32_t idx) "for setting frequency for lcore %u\n", pi->lcore_id); return -1; } + /* we use unbuffered mode so following will fail if kernel will refuse + * freq setting */ if (fprintf(pi->f, "%u", pi->freqs[idx]) < 0) { RTE_LOG(ERR, POWER, "Fail to write new frequency for " "lcore %u\n", pi->lcore_id); return -1; } - fflush(pi->f); pi->curr_idx = idx; return 1; @@ -174,6 +175,11 @@ power_set_governor_userspace(struct rte_power_info *pi) f = fopen(fullpath, "rw+"); FOPEN_OR_ERR_RET(f, ret); + if (setvbuf(f, NULL, _IONBF, 0)) { + RTE_LOG(ERR, POWER, "Cannot set unbuffered mode\n"); + goto out; + } + s = fgets(buf, sizeof(buf), f); FOPS_OR_NULL_GOTO(s, out); @@ -292,6 +298,11 @@ power_init_for_setting_freq(struct rte_power_info *pi) f = fopen(fullpath, "rw+"); FOPEN_OR_ERR_RET(f, -1); + if (setvbuf(f, NULL, _IONBF, 0)) { + RTE_LOG(ERR, POWER, "Cannot set unbuffered mode\n"); + goto out; + } + s = fgets(buf, sizeof(buf), f); FOPS_OR_NULL_GOTO(s, out); @@ -389,6 +400,11 @@ power_set_governor_original(struct rte_power_info *pi) f = fopen(fullpath, "rw+"); FOPEN_OR_ERR_RET(f, ret); + if (setvbuf(f, NULL, _IONBF, 0)) { + RTE_LOG(ERR, POWER, "Cannot set unbuffered mode\n"); + goto out; + } + s = fgets(buf, sizeof(buf), f); FOPS_OR_NULL_GOTO(s, out); -- 2.7.4 ^ permalink raw reply [flat|nested] 15+ messages in thread
* [dpdk-dev] [PATCH 2/2] power: check if userspace governor is available 2017-10-16 13:47 [dpdk-dev] [PATCH 1/2] power: switching to unbuffered stdio for /sys file access Radoslaw Biernacki @ 2017-10-16 13:47 ` Radoslaw Biernacki 2017-10-18 10:53 ` Hunt, David 2017-10-18 10:28 ` [dpdk-dev] [PATCH 1/2] power: switching to unbuffered stdio for /sys file access Hunt, David ` (2 subsequent siblings) 3 siblings, 1 reply; 15+ messages in thread From: Radoslaw Biernacki @ 2017-10-16 13:47 UTC (permalink / raw) To: dev, david.hunt; +Cc: stable, alan.carew, pablo.de.lara.guarch Since for new Intel CPU's kernel use intel_pstate driver, which does not offer userspace governor, it is vise to check the userspace governor availability before trying to perform governor switch. The outcome from this patch is direct information for user about the root cause of failure during the rte_power_acpi_cpufreq_init(). This patch also add the /sys file name to error message as on some platforms some files expected by this rte_power are not available. This is also useful for pinning down the root cause of the problem. Signed-off-by: Radoslaw Biernacki <radoslaw.biernacki@linaro.org> --- lib/librte_power/rte_power_acpi_cpufreq.c | 35 ++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/lib/librte_power/rte_power_acpi_cpufreq.c b/lib/librte_power/rte_power_acpi_cpufreq.c index 8bf5685..342eb22 100644 --- a/lib/librte_power/rte_power_acpi_cpufreq.c +++ b/lib/librte_power/rte_power_acpi_cpufreq.c @@ -55,9 +55,9 @@ #define POWER_DEBUG_TRACE(fmt, args...) #endif -#define FOPEN_OR_ERR_RET(f, retval) do { \ +#define FOPEN_OR_ERR_RET(f, fullpath, retval) do { \ if ((f) == NULL) { \ - RTE_LOG(ERR, POWER, "File not openned\n"); \ + RTE_LOG(ERR, POWER, "File %s not openned\n", fullpath); \ return retval; \ } \ } while (0) @@ -80,6 +80,8 @@ #define POWER_CONVERT_TO_DECIMAL 10 #define POWER_GOVERNOR_USERSPACE "userspace" +#define POWER_SYSFILE_AVAIL_GOVERNOR \ + "/sys/devices/system/cpu/cpu%u/cpufreq/scaling_available_governors" #define POWER_SYSFILE_GOVERNOR \ "/sys/devices/system/cpu/cpu%u/cpufreq/scaling_governor" #define POWER_SYSFILE_AVAIL_FREQ \ @@ -170,10 +172,28 @@ power_set_governor_userspace(struct rte_power_info *pi) char *s; int val; + /* check if userspace governor is available */ + + snprintf(fullpath, sizeof(fullpath), POWER_SYSFILE_AVAIL_GOVERNOR, + pi->lcore_id); + f = fopen(fullpath, "r"); + FOPEN_OR_ERR_RET(f, fullpath, ret); + + s = fgets(buf, sizeof(buf), f); + FOPS_OR_NULL_GOTO(s, out); + + if (!strstr(buf, POWER_GOVERNOR_USERSPACE)) { + RTE_LOG(ERR, POWER, "Userspace governor is not available\n"); + goto out; + } + fclose(f); + + /* store current governor and set userspace governor */ + snprintf(fullpath, sizeof(fullpath), POWER_SYSFILE_GOVERNOR, pi->lcore_id); f = fopen(fullpath, "rw+"); - FOPEN_OR_ERR_RET(f, ret); + FOPEN_OR_ERR_RET(f, fullpath, ret); if (setvbuf(f, NULL, _IONBF, 0)) { RTE_LOG(ERR, POWER, "Cannot set unbuffered mode\n"); @@ -184,8 +204,7 @@ power_set_governor_userspace(struct rte_power_info *pi) FOPS_OR_NULL_GOTO(s, out); /* Check if current governor is userspace */ - if (strncmp(buf, POWER_GOVERNOR_USERSPACE, - sizeof(POWER_GOVERNOR_USERSPACE)) == 0) { + if (!strcmp(buf, POWER_GOVERNOR_USERSPACE)) { ret = 0; POWER_DEBUG_TRACE("Power management governor of lcore %u is " "already userspace\n", pi->lcore_id); @@ -228,7 +247,7 @@ power_get_available_freqs(struct rte_power_info *pi) snprintf(fullpath, sizeof(fullpath), POWER_SYSFILE_AVAIL_FREQ, pi->lcore_id); f = fopen(fullpath, "r"); - FOPEN_OR_ERR_RET(f, ret); + FOPEN_OR_ERR_RET(f, fullpath, ret); s = fgets(buf, sizeof(buf), f); FOPS_OR_NULL_GOTO(s, out); @@ -296,7 +315,7 @@ power_init_for_setting_freq(struct rte_power_info *pi) snprintf(fullpath, sizeof(fullpath), POWER_SYSFILE_SETSPEED, pi->lcore_id); f = fopen(fullpath, "rw+"); - FOPEN_OR_ERR_RET(f, -1); + FOPEN_OR_ERR_RET(f, fullpath, -1); if (setvbuf(f, NULL, _IONBF, 0)) { RTE_LOG(ERR, POWER, "Cannot set unbuffered mode\n"); @@ -398,7 +417,7 @@ power_set_governor_original(struct rte_power_info *pi) snprintf(fullpath, sizeof(fullpath), POWER_SYSFILE_GOVERNOR, pi->lcore_id); f = fopen(fullpath, "rw+"); - FOPEN_OR_ERR_RET(f, ret); + FOPEN_OR_ERR_RET(f, fullpath, ret); if (setvbuf(f, NULL, _IONBF, 0)) { RTE_LOG(ERR, POWER, "Cannot set unbuffered mode\n"); -- 2.7.4 ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [dpdk-dev] [PATCH 2/2] power: check if userspace governor is available 2017-10-16 13:47 ` [dpdk-dev] [PATCH 2/2] power: check if userspace governor is available Radoslaw Biernacki @ 2017-10-18 10:53 ` Hunt, David 2017-10-18 14:02 ` Radoslaw Biernacki 0 siblings, 1 reply; 15+ messages in thread From: Hunt, David @ 2017-10-18 10:53 UTC (permalink / raw) To: Radoslaw Biernacki, dev; +Cc: stable, alan.carew, pablo.de.lara.guarch Hi Radoslaw, On 16/10/2017 2:47 PM, Radoslaw Biernacki wrote: > Since for new Intel CPU's kernel use intel_pstate driver, > which does not offer userspace governor, it is vise to check typo here, "wise" > the userspace governor availability before trying to perform > governor switch. The outcome from this patch is direct > information for user about the root cause of failure during > the rte_power_acpi_cpufreq_init(). This patch also add the > /sys file name to error message as on some platforms some > files expected by this rte_power are not available. This is > also useful for pinning down the root cause of the problem. Good suggestion. It's a useful change. What would you think of also adding a check of the contents of the "scaling_driver" file? This would indicate the reason why the userspace governor is not available. If it's "intel_pstate", then we could suggest to the user that "intel_pstate=disable" needs to be added to the kernel boot parameters. > Signed-off-by: Radoslaw Biernacki <radoslaw.biernacki@linaro.org> > --- > lib/librte_power/rte_power_acpi_cpufreq.c | 35 ++++++++++++++++++++++++------- > 1 file changed, 27 insertions(+), 8 deletions(-) > > diff --git a/lib/librte_power/rte_power_acpi_cpufreq.c b/lib/librte_power/rte_power_acpi_cpufreq.c > index 8bf5685..342eb22 100644 > --- a/lib/librte_power/rte_power_acpi_cpufreq.c > +++ b/lib/librte_power/rte_power_acpi_cpufreq.c > @@ -55,9 +55,9 @@ > #define POWER_DEBUG_TRACE(fmt, args...) > #endif > > -#define FOPEN_OR_ERR_RET(f, retval) do { \ > +#define FOPEN_OR_ERR_RET(f, fullpath, retval) do { \ > if ((f) == NULL) { \ > - RTE_LOG(ERR, POWER, "File not openned\n"); \ > + RTE_LOG(ERR, POWER, "File %s not openned\n", fullpath); \ > return retval; \ > } \ > } while (0) There's a checkpatch error here. I've encountered this one a few times in the past, and I don't believe it can be fixed with the macro in it's current form. Later versions of checkpatch does not like control statements in macros, so the only way to fix this checkpatch problem is to remove the macro, and put the 'if' statement back into the code instead of calling the macro. As well as fixing the checkpatch issue, I feel this would have the added advantage of making the code more readable. Also, I would suggest changing "File %s not openned\n" to "Failed to open %s.\n". > @@ -80,6 +80,8 @@ > #define POWER_CONVERT_TO_DECIMAL 10 > > #define POWER_GOVERNOR_USERSPACE "userspace" > +#define POWER_SYSFILE_AVAIL_GOVERNOR \ > + "/sys/devices/system/cpu/cpu%u/cpufreq/scaling_available_governors" > #define POWER_SYSFILE_GOVERNOR \ > "/sys/devices/system/cpu/cpu%u/cpufreq/scaling_governor" > #define POWER_SYSFILE_AVAIL_FREQ \ > @@ -170,10 +172,28 @@ power_set_governor_userspace(struct rte_power_info *pi) > char *s; > int val; > > + /* check if userspace governor is available */ > + > + snprintf(fullpath, sizeof(fullpath), POWER_SYSFILE_AVAIL_GOVERNOR, > + pi->lcore_id); > + f = fopen(fullpath, "r"); > + FOPEN_OR_ERR_RET(f, fullpath, ret); > + > + s = fgets(buf, sizeof(buf), f); > + FOPS_OR_NULL_GOTO(s, out); > + > + if (!strstr(buf, POWER_GOVERNOR_USERSPACE)) { > + RTE_LOG(ERR, POWER, "Userspace governor is not available\n"); > + goto out; > + } > + fclose(f); > + > + /* store current governor and set userspace governor */ > + > snprintf(fullpath, sizeof(fullpath), POWER_SYSFILE_GOVERNOR, > pi->lcore_id); > f = fopen(fullpath, "rw+"); > - FOPEN_OR_ERR_RET(f, ret); > + FOPEN_OR_ERR_RET(f, fullpath, ret); > > if (setvbuf(f, NULL, _IONBF, 0)) { > RTE_LOG(ERR, POWER, "Cannot set unbuffered mode\n"); > @@ -184,8 +204,7 @@ power_set_governor_userspace(struct rte_power_info *pi) > FOPS_OR_NULL_GOTO(s, out); > > /* Check if current governor is userspace */ > - if (strncmp(buf, POWER_GOVERNOR_USERSPACE, > - sizeof(POWER_GOVERNOR_USERSPACE)) == 0) { > + if (!strcmp(buf, POWER_GOVERNOR_USERSPACE)) { > ret = 0; > POWER_DEBUG_TRACE("Power management governor of lcore %u is " > "already userspace\n", pi->lcore_id); > @@ -228,7 +247,7 @@ power_get_available_freqs(struct rte_power_info *pi) > snprintf(fullpath, sizeof(fullpath), POWER_SYSFILE_AVAIL_FREQ, > pi->lcore_id); > f = fopen(fullpath, "r"); > - FOPEN_OR_ERR_RET(f, ret); > + FOPEN_OR_ERR_RET(f, fullpath, ret); > > s = fgets(buf, sizeof(buf), f); > FOPS_OR_NULL_GOTO(s, out); > @@ -296,7 +315,7 @@ power_init_for_setting_freq(struct rte_power_info *pi) > snprintf(fullpath, sizeof(fullpath), POWER_SYSFILE_SETSPEED, > pi->lcore_id); > f = fopen(fullpath, "rw+"); > - FOPEN_OR_ERR_RET(f, -1); > + FOPEN_OR_ERR_RET(f, fullpath, -1); > > if (setvbuf(f, NULL, _IONBF, 0)) { > RTE_LOG(ERR, POWER, "Cannot set unbuffered mode\n"); > @@ -398,7 +417,7 @@ power_set_governor_original(struct rte_power_info *pi) > snprintf(fullpath, sizeof(fullpath), POWER_SYSFILE_GOVERNOR, > pi->lcore_id); > f = fopen(fullpath, "rw+"); > - FOPEN_OR_ERR_RET(f, ret); > + FOPEN_OR_ERR_RET(f, fullpath, ret); > > if (setvbuf(f, NULL, _IONBF, 0)) { > RTE_LOG(ERR, POWER, "Cannot set unbuffered mode\n"); Thanks, Dave. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [dpdk-dev] [PATCH 2/2] power: check if userspace governor is available 2017-10-18 10:53 ` Hunt, David @ 2017-10-18 14:02 ` Radoslaw Biernacki 0 siblings, 0 replies; 15+ messages in thread From: Radoslaw Biernacki @ 2017-10-18 14:02 UTC (permalink / raw) To: Hunt, David; +Cc: dev, stable, alan.carew, pablo.de.lara.guarch Hi David, On 18 October 2017 at 12:53, Hunt, David <david.hunt@intel.com> wrote: > Hi Radoslaw, > > > On 16/10/2017 2:47 PM, Radoslaw Biernacki wrote: > >> Since for new Intel CPU's kernel use intel_pstate driver, >> which does not offer userspace governor, it is vise to check >> > > typo here, "wise" > > the userspace governor availability before trying to perform >> governor switch. The outcome from this patch is direct >> information for user about the root cause of failure during >> the rte_power_acpi_cpufreq_init(). This patch also add the >> /sys file name to error message as on some platforms some >> files expected by this rte_power are not available. This is >> also useful for pinning down the root cause of the problem. >> > > Good suggestion. It's a useful change. > > What would you think of also adding a check of the contents of the > "scaling_driver" file? This would indicate the reason why the userspace > governor is not available. > If it's "intel_pstate", then we could suggest to the user that > "intel_pstate=disable" needs to be added to the kernel boot parameters. Yes, will do. This will save time of DPDK users trying to figure out the problem. > > > Signed-off-by: Radoslaw Biernacki <radoslaw.biernacki@linaro.org> >> --- >> lib/librte_power/rte_power_acpi_cpufreq.c | 35 >> ++++++++++++++++++++++++------- >> 1 file changed, 27 insertions(+), 8 deletions(-) >> >> diff --git a/lib/librte_power/rte_power_acpi_cpufreq.c >> b/lib/librte_power/rte_power_acpi_cpufreq.c >> index 8bf5685..342eb22 100644 >> --- a/lib/librte_power/rte_power_acpi_cpufreq.c >> +++ b/lib/librte_power/rte_power_acpi_cpufreq.c >> @@ -55,9 +55,9 @@ >> #define POWER_DEBUG_TRACE(fmt, args...) >> #endif >> -#define FOPEN_OR_ERR_RET(f, retval) do { \ >> +#define FOPEN_OR_ERR_RET(f, fullpath, retval) do { \ >> if ((f) == NULL) { \ >> - RTE_LOG(ERR, POWER, "File not openned\n"); \ >> + RTE_LOG(ERR, POWER, "File %s not openned\n", >> fullpath); \ >> return retval; \ >> } \ >> } while (0) >> > > There's a checkpatch error here. I've encountered this one a few times in > the past, and I don't believe it can be fixed with the macro in it's > current form. Later versions of checkpatch does not like control statements > in macros, so the only way to fix this checkpatch problem is to remove the > macro, and put the 'if' statement back into the code instead of calling the > macro. As well as fixing the checkpatch issue, I feel this would have the > added advantage of making the code more readable. > > Also, I would suggest changing "File %s not openned\n" to "Failed to open > %s.\n". Sure, will fix those as well in V2 > > > @@ -80,6 +80,8 @@ >> #define POWER_CONVERT_TO_DECIMAL 10 >> #define POWER_GOVERNOR_USERSPACE "userspace" >> +#define POWER_SYSFILE_AVAIL_GOVERNOR \ >> + "/sys/devices/system/cpu/cpu% >> u/cpufreq/scaling_available_governors" >> #define POWER_SYSFILE_GOVERNOR \ >> "/sys/devices/system/cpu/cpu%u/cpufreq/scaling_governor" >> #define POWER_SYSFILE_AVAIL_FREQ \ >> @@ -170,10 +172,28 @@ power_set_governor_userspace(struct rte_power_info >> *pi) >> char *s; >> int val; >> + /* check if userspace governor is available */ >> + >> + snprintf(fullpath, sizeof(fullpath), POWER_SYSFILE_AVAIL_GOVERNOR, >> + pi->lcore_id); >> + f = fopen(fullpath, "r"); >> + FOPEN_OR_ERR_RET(f, fullpath, ret); >> + >> + s = fgets(buf, sizeof(buf), f); >> + FOPS_OR_NULL_GOTO(s, out); >> + >> + if (!strstr(buf, POWER_GOVERNOR_USERSPACE)) { >> + RTE_LOG(ERR, POWER, "Userspace governor is not >> available\n"); >> + goto out; >> + } >> + fclose(f); >> + >> + /* store current governor and set userspace governor */ >> + >> snprintf(fullpath, sizeof(fullpath), POWER_SYSFILE_GOVERNOR, >> pi->lcore_id); >> f = fopen(fullpath, "rw+"); >> - FOPEN_OR_ERR_RET(f, ret); >> + FOPEN_OR_ERR_RET(f, fullpath, ret); >> if (setvbuf(f, NULL, _IONBF, 0)) { >> RTE_LOG(ERR, POWER, "Cannot set unbuffered mode\n"); >> @@ -184,8 +204,7 @@ power_set_governor_userspace(struct rte_power_info >> *pi) >> FOPS_OR_NULL_GOTO(s, out); >> /* Check if current governor is userspace */ >> - if (strncmp(buf, POWER_GOVERNOR_USERSPACE, >> - sizeof(POWER_GOVERNOR_USERSPACE)) == 0) { >> + if (!strcmp(buf, POWER_GOVERNOR_USERSPACE)) { >> ret = 0; >> POWER_DEBUG_TRACE("Power management governor of lcore %u >> is " >> "already userspace\n", pi->lcore_id); >> @@ -228,7 +247,7 @@ power_get_available_freqs(struct rte_power_info *pi) >> snprintf(fullpath, sizeof(fullpath), POWER_SYSFILE_AVAIL_FREQ, >> pi->lcore_id); >> f = fopen(fullpath, "r"); >> - FOPEN_OR_ERR_RET(f, ret); >> + FOPEN_OR_ERR_RET(f, fullpath, ret); >> s = fgets(buf, sizeof(buf), f); >> FOPS_OR_NULL_GOTO(s, out); >> @@ -296,7 +315,7 @@ power_init_for_setting_freq(struct rte_power_info >> *pi) >> snprintf(fullpath, sizeof(fullpath), POWER_SYSFILE_SETSPEED, >> pi->lcore_id); >> f = fopen(fullpath, "rw+"); >> - FOPEN_OR_ERR_RET(f, -1); >> + FOPEN_OR_ERR_RET(f, fullpath, -1); >> if (setvbuf(f, NULL, _IONBF, 0)) { >> RTE_LOG(ERR, POWER, "Cannot set unbuffered mode\n"); >> @@ -398,7 +417,7 @@ power_set_governor_original(struct rte_power_info >> *pi) >> snprintf(fullpath, sizeof(fullpath), POWER_SYSFILE_GOVERNOR, >> pi->lcore_id); >> f = fopen(fullpath, "rw+"); >> - FOPEN_OR_ERR_RET(f, ret); >> + FOPEN_OR_ERR_RET(f, fullpath, ret); >> if (setvbuf(f, NULL, _IONBF, 0)) { >> RTE_LOG(ERR, POWER, "Cannot set unbuffered mode\n"); >> > > Thanks, > Dave. > ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [dpdk-dev] [PATCH 1/2] power: switching to unbuffered stdio for /sys file access 2017-10-16 13:47 [dpdk-dev] [PATCH 1/2] power: switching to unbuffered stdio for /sys file access Radoslaw Biernacki 2017-10-16 13:47 ` [dpdk-dev] [PATCH 2/2] power: check if userspace governor is available Radoslaw Biernacki @ 2017-10-18 10:28 ` Hunt, David 2017-10-18 10:33 ` Hunt, David 2017-11-11 18:55 ` [dpdk-dev] [PATCH 0/3] power: fixes for power ACPI through sysfs Radoslaw Biernacki 3 siblings, 0 replies; 15+ messages in thread From: Hunt, David @ 2017-10-18 10:28 UTC (permalink / raw) To: Radoslaw Biernacki, dev; +Cc: stable, alan.carew, pablo.de.lara.guarch Hi Radoslaw, Thanks for the patch. Some comments below. On 16/10/2017 2:47 PM, Radoslaw Biernacki wrote: > This patch fixes the bug caused by improper use of buffered > stdio file access for switching the CPU frequency and > governor. Each write operation when using buffered stdio > must be flushed out and the return code from fflush() must > be verified. In buffered mode, write() syscall return value > is is not returned by fwrite()/fputs()/fprintf(). > Since with buffered approatch, fflush() need to be done > every time it is better to use unbuffered mode or not use > stdio at all (instead use plain open/write functions). To > minimize amount of changes this fix use first approach. > > Signed-off-by: Radoslaw Biernacki <radoslaw.biernacki@linaro.org> > --- > lib/librte_power/rte_power_acpi_cpufreq.c | 18 +++++++++++++++++- > 1 file changed, 17 insertions(+), 1 deletion(-) > > diff --git a/lib/librte_power/rte_power_acpi_cpufreq.c b/lib/librte_power/rte_power_acpi_cpufreq.c > index 01ac5ac..8bf5685 100644 > --- a/lib/librte_power/rte_power_acpi_cpufreq.c > +++ b/lib/librte_power/rte_power_acpi_cpufreq.c > @@ -143,12 +143,13 @@ set_freq_internal(struct rte_power_info *pi, uint32_t idx) > "for setting frequency for lcore %u\n", pi->lcore_id); > return -1; > } > + /* we use unbuffered mode so following will fail if kernel will refuse > + * freq setting */ > if (fprintf(pi->f, "%u", pi->freqs[idx]) < 0) { > RTE_LOG(ERR, POWER, "Fail to write new frequency for " > "lcore %u\n", pi->lcore_id); > return -1; > } > - fflush(pi->f); > pi->curr_idx = idx; > One suggestion to to avoid switching to unbuffered mode would be to move the check from the fprintf to the fflush. That would eliminate the need for the changes below, keeping the changes to a minimum. But I also agree that open/write would be a better option, should you prefer to go that route. > return 1; > @@ -174,6 +175,11 @@ power_set_governor_userspace(struct rte_power_info *pi) > f = fopen(fullpath, "rw+"); > FOPEN_OR_ERR_RET(f, ret); > > + if (setvbuf(f, NULL, _IONBF, 0)) { > + RTE_LOG(ERR, POWER, "Cannot set unbuffered mode\n"); > + goto out; > + } > + > s = fgets(buf, sizeof(buf), f); > FOPS_OR_NULL_GOTO(s, out); > > @@ -292,6 +298,11 @@ power_init_for_setting_freq(struct rte_power_info *pi) > f = fopen(fullpath, "rw+"); > FOPEN_OR_ERR_RET(f, -1); > > + if (setvbuf(f, NULL, _IONBF, 0)) { > + RTE_LOG(ERR, POWER, "Cannot set unbuffered mode\n"); > + goto out; > + } > + > s = fgets(buf, sizeof(buf), f); > FOPS_OR_NULL_GOTO(s, out); > > @@ -389,6 +400,11 @@ power_set_governor_original(struct rte_power_info *pi) > f = fopen(fullpath, "rw+"); > FOPEN_OR_ERR_RET(f, ret); > > + if (setvbuf(f, NULL, _IONBF, 0)) { > + RTE_LOG(ERR, POWER, "Cannot set unbuffered mode\n"); > + goto out; > + } > + > s = fgets(buf, sizeof(buf), f); > FOPS_OR_NULL_GOTO(s, out); > Regards, Dave ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [dpdk-dev] [PATCH 1/2] power: switching to unbuffered stdio for /sys file access 2017-10-16 13:47 [dpdk-dev] [PATCH 1/2] power: switching to unbuffered stdio for /sys file access Radoslaw Biernacki 2017-10-16 13:47 ` [dpdk-dev] [PATCH 2/2] power: check if userspace governor is available Radoslaw Biernacki 2017-10-18 10:28 ` [dpdk-dev] [PATCH 1/2] power: switching to unbuffered stdio for /sys file access Hunt, David @ 2017-10-18 10:33 ` Hunt, David 2017-10-18 13:56 ` Radoslaw Biernacki 2017-11-11 18:55 ` [dpdk-dev] [PATCH 0/3] power: fixes for power ACPI through sysfs Radoslaw Biernacki 3 siblings, 1 reply; 15+ messages in thread From: Hunt, David @ 2017-10-18 10:33 UTC (permalink / raw) To: Radoslaw Biernacki, dev; +Cc: stable, alan.carew, pablo.de.lara.guarch Hi Radoslaw, On 16/10/2017 2:47 PM, Radoslaw Biernacki wrote: > This patch fixes the bug caused by improper use of buffered > stdio file access for switching the CPU frequency and > governor. Each write operation when using buffered stdio > must be flushed out and the return code from fflush() must > be verified. In buffered mode, write() syscall return value > is is not returned by fwrite()/fputs()/fprintf(). > Since with buffered approatch, fflush() need to be done > every time it is better to use unbuffered mode or not use > stdio at all (instead use plain open/write functions). To > minimize amount of changes this fix use first approach. > > Signed-off-by: Radoslaw Biernacki <radoslaw.biernacki@linaro.org> > --- > lib/librte_power/rte_power_acpi_cpufreq.c | 18 +++++++++++++++++- > 1 file changed, 17 insertions(+), 1 deletion(-) > > diff --git a/lib/librte_power/rte_power_acpi_cpufreq.c b/lib/librte_power/rte_power_acpi_cpufreq.c > index 01ac5ac..8bf5685 100644 > --- a/lib/librte_power/rte_power_acpi_cpufreq.c > +++ b/lib/librte_power/rte_power_acpi_cpufreq.c > @@ -143,12 +143,13 @@ set_freq_internal(struct rte_power_info *pi, uint32_t idx) > "for setting frequency for lcore %u\n", pi->lcore_id); > return -1; > } > + /* we use unbuffered mode so following will fail if kernel will refuse > + * freq setting */ Also, there's an issue with checkpatch on the comment here. Please make sure to run your patches through checkpatch. Typically a recent version of checkpatch should be used (4.1x). Rgds, Dave. ---snip--- ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [dpdk-dev] [PATCH 1/2] power: switching to unbuffered stdio for /sys file access 2017-10-18 10:33 ` Hunt, David @ 2017-10-18 13:56 ` Radoslaw Biernacki 0 siblings, 0 replies; 15+ messages in thread From: Radoslaw Biernacki @ 2017-10-18 13:56 UTC (permalink / raw) To: Hunt, David; +Cc: dev, stable, alan.carew, pablo.de.lara.guarch Hi David, Thank you for comments. On 18 October 2017 at 12:33, Hunt, David <david.hunt@intel.com> wrote: > Hi Radoslaw, > > > On 16/10/2017 2:47 PM, Radoslaw Biernacki wrote: > >> This patch fixes the bug caused by improper use of buffered >> stdio file access for switching the CPU frequency and >> governor. Each write operation when using buffered stdio >> must be flushed out and the return code from fflush() must >> be verified. In buffered mode, write() syscall return value >> is is not returned by fwrite()/fputs()/fprintf(). >> Since with buffered approatch, fflush() need to be done >> every time it is better to use unbuffered mode or not use >> stdio at all (instead use plain open/write functions). To >> minimize amount of changes this fix use first approach. >> >> Signed-off-by: Radoslaw Biernacki <radoslaw.biernacki@linaro.org> >> --- >> lib/librte_power/rte_power_acpi_cpufreq.c | 18 +++++++++++++++++- >> 1 file changed, 17 insertions(+), 1 deletion(-) >> >> diff --git a/lib/librte_power/rte_power_acpi_cpufreq.c >> b/lib/librte_power/rte_power_acpi_cpufreq.c >> index 01ac5ac..8bf5685 100644 >> --- a/lib/librte_power/rte_power_acpi_cpufreq.c >> +++ b/lib/librte_power/rte_power_acpi_cpufreq.c >> @@ -143,12 +143,13 @@ set_freq_internal(struct rte_power_info *pi, >> uint32_t idx) >> "for setting frequency for lcore %u\n", >> pi->lcore_id); >> return -1; >> } >> + /* we use unbuffered mode so following will fail if kernel will >> refuse >> + * freq setting */ >> > > Also, there's an issue with checkpatch on the comment here. Please make > sure to run your patches through checkpatch. Typically a recent version of > checkpatch should be used (4.1x). > I apologise for missing checkpatch, seems that problems with my environment settings cause the silent output. Will never happen again. ---snip--- For the option of using open/write: yes, as you agreed with that, let me prepare V2 of those fixes. ^ permalink raw reply [flat|nested] 15+ messages in thread
* [dpdk-dev] [PATCH 0/3] power: fixes for power ACPI through sysfs 2017-10-16 13:47 [dpdk-dev] [PATCH 1/2] power: switching to unbuffered stdio for /sys file access Radoslaw Biernacki ` (2 preceding siblings ...) 2017-10-18 10:33 ` Hunt, David @ 2017-11-11 18:55 ` Radoslaw Biernacki 2017-11-11 18:55 ` [dpdk-dev] [PATCH 1/3] power: removing code macros Radoslaw Biernacki ` (3 more replies) 3 siblings, 4 replies; 15+ messages in thread From: Radoslaw Biernacki @ 2017-11-11 18:55 UTC (permalink / raw) To: dev, david.hunt; +Cc: stable, alan.carew, pablo.de.lara.guarch This series of patches is fixing bug in power ACPI subsystem code as well as improve the debugging messages and cleans the code. V2: - error checking macros removed (checkpatch warning) - using plain open()/read()/write() system functions instead of STDIO - added check for intel_pstate driver together with suggestion about needed kernel boot parameter Radoslaw Biernacki (3): power: removing code macros power: switching to unbuffered access for /sys files power: check if userspace governor is available lib/librte_power/rte_power_acpi_cpufreq.c | 304 ++++++++++++++++++------------ 1 file changed, 182 insertions(+), 122 deletions(-) -- 2.7.4 ^ permalink raw reply [flat|nested] 15+ messages in thread
* [dpdk-dev] [PATCH 1/3] power: removing code macros 2017-11-11 18:55 ` [dpdk-dev] [PATCH 0/3] power: fixes for power ACPI through sysfs Radoslaw Biernacki @ 2017-11-11 18:55 ` Radoslaw Biernacki 2017-11-11 18:55 ` [dpdk-dev] [PATCH 2/3] power: switching to unbuffered access for /sys files Radoslaw Biernacki ` (2 subsequent siblings) 3 siblings, 0 replies; 15+ messages in thread From: Radoslaw Biernacki @ 2017-11-11 18:55 UTC (permalink / raw) To: dev, david.hunt; +Cc: stable, alan.carew, pablo.de.lara.guarch This fix implements David Hunt suggestion to remove error checking code macros. Together with improved code readability it removes checkpatch warnings. Fixes: 445c6528b55f ("power: common interface for guest and host") CC: stable@dpdk.org Signed-off-by: Radoslaw Biernacki <radoslaw.biernacki@linaro.org> --- lib/librte_power/rte_power_acpi_cpufreq.c | 81 ++++++++++++++++++------------- 1 file changed, 48 insertions(+), 33 deletions(-) diff --git a/lib/librte_power/rte_power_acpi_cpufreq.c b/lib/librte_power/rte_power_acpi_cpufreq.c index 01ac5ac..3d0872f 100644 --- a/lib/librte_power/rte_power_acpi_cpufreq.c +++ b/lib/librte_power/rte_power_acpi_cpufreq.c @@ -55,27 +55,6 @@ #define POWER_DEBUG_TRACE(fmt, args...) #endif -#define FOPEN_OR_ERR_RET(f, retval) do { \ - if ((f) == NULL) { \ - RTE_LOG(ERR, POWER, "File not openned\n"); \ - return retval; \ - } \ -} while (0) - -#define FOPS_OR_NULL_GOTO(ret, label) do { \ - if ((ret) == NULL) { \ - RTE_LOG(ERR, POWER, "fgets returns nothing\n"); \ - goto label; \ - } \ -} while (0) - -#define FOPS_OR_ERR_GOTO(ret, label) do { \ - if ((ret) < 0) { \ - RTE_LOG(ERR, POWER, "File operations failed\n"); \ - goto label; \ - } \ -} while (0) - #define STR_SIZE 1024 #define POWER_CONVERT_TO_DECIMAL 10 @@ -172,10 +151,16 @@ power_set_governor_userspace(struct rte_power_info *pi) snprintf(fullpath, sizeof(fullpath), POWER_SYSFILE_GOVERNOR, pi->lcore_id); f = fopen(fullpath, "rw+"); - FOPEN_OR_ERR_RET(f, ret); + if (!f) { + RTE_LOG(ERR, POWER, "Failed to open %s\n", fullpath); + return ret; + } s = fgets(buf, sizeof(buf), f); - FOPS_OR_NULL_GOTO(s, out); + if (!s) { + RTE_LOG(ERR, POWER, "fgets returns nothing\n"); + goto out; + } /* Check if current governor is userspace */ if (strncmp(buf, POWER_GOVERNOR_USERSPACE, @@ -190,10 +175,16 @@ power_set_governor_userspace(struct rte_power_info *pi) /* Write 'userspace' to the governor */ val = fseek(f, 0, SEEK_SET); - FOPS_OR_ERR_GOTO(val, out); + if (val < 0) { + RTE_LOG(ERR, POWER, "fseek failed\n"); + goto out; + } val = fputs(POWER_GOVERNOR_USERSPACE, f); - FOPS_OR_ERR_GOTO(val, out); + if (val < 0) { + RTE_LOG(ERR, POWER, "fputs failed\n"); + goto out; + } ret = 0; RTE_LOG(INFO, POWER, "Power management governor of lcore %u has been " @@ -222,10 +213,16 @@ power_get_available_freqs(struct rte_power_info *pi) snprintf(fullpath, sizeof(fullpath), POWER_SYSFILE_AVAIL_FREQ, pi->lcore_id); f = fopen(fullpath, "r"); - FOPEN_OR_ERR_RET(f, ret); + if (!f) { + RTE_LOG(ERR, POWER, "Failed to open %s\n", fullpath); + return ret; + } s = fgets(buf, sizeof(buf), f); - FOPS_OR_NULL_GOTO(s, out); + if (!s) { + RTE_LOG(ERR, POWER, "fgets returns nothing\n"); + goto out; + } /* Strip the line break if there is */ p = strchr(buf, '\n'); @@ -290,10 +287,16 @@ power_init_for_setting_freq(struct rte_power_info *pi) snprintf(fullpath, sizeof(fullpath), POWER_SYSFILE_SETSPEED, pi->lcore_id); f = fopen(fullpath, "rw+"); - FOPEN_OR_ERR_RET(f, -1); + if (!f) { + RTE_LOG(ERR, POWER, "Failed to open %s\n", fullpath); + return -1; + } s = fgets(buf, sizeof(buf), f); - FOPS_OR_NULL_GOTO(s, out); + if (!s) { + RTE_LOG(ERR, POWER, "fgets returns nothing\n"); + goto out; + } freq = strtoul(buf, NULL, POWER_CONVERT_TO_DECIMAL); for (i = 0; i < pi->nb_freqs; i++) { @@ -387,10 +390,16 @@ power_set_governor_original(struct rte_power_info *pi) snprintf(fullpath, sizeof(fullpath), POWER_SYSFILE_GOVERNOR, pi->lcore_id); f = fopen(fullpath, "rw+"); - FOPEN_OR_ERR_RET(f, ret); + if (!f) { + RTE_LOG(ERR, POWER, "Failed to open %s\n", fullpath); + return ret; + } s = fgets(buf, sizeof(buf), f); - FOPS_OR_NULL_GOTO(s, out); + if (!s) { + RTE_LOG(ERR, POWER, "fgets returns nothing\n"); + goto out; + } /* Check if the governor to be set is the same as current */ if (strncmp(buf, pi->governor_ori, sizeof(pi->governor_ori)) == 0) { @@ -403,10 +412,16 @@ power_set_governor_original(struct rte_power_info *pi) /* Write back the original governor */ val = fseek(f, 0, SEEK_SET); - FOPS_OR_ERR_GOTO(val, out); + if (val < 0) { + RTE_LOG(ERR, POWER, "fseek failed\n"); + goto out; + } val = fputs(pi->governor_ori, f); - FOPS_OR_ERR_GOTO(val, out); + if (val < 0) { + RTE_LOG(ERR, POWER, "fputs failed\n"); + goto out; + } ret = 0; RTE_LOG(INFO, POWER, "Power management governor of lcore %u " -- 2.7.4 ^ permalink raw reply [flat|nested] 15+ messages in thread
* [dpdk-dev] [PATCH 2/3] power: switching to unbuffered access for /sys files 2017-11-11 18:55 ` [dpdk-dev] [PATCH 0/3] power: fixes for power ACPI through sysfs Radoslaw Biernacki 2017-11-11 18:55 ` [dpdk-dev] [PATCH 1/3] power: removing code macros Radoslaw Biernacki @ 2017-11-11 18:55 ` Radoslaw Biernacki 2017-11-23 14:42 ` Hunt, David 2017-11-11 18:55 ` [dpdk-dev] [PATCH 3/3] power: check if userspace governor is available Radoslaw Biernacki 2017-11-21 11:09 ` [dpdk-dev] [PATCH 0/3] power: fixes for power ACPI through sysfs Radoslaw Biernacki 3 siblings, 1 reply; 15+ messages in thread From: Radoslaw Biernacki @ 2017-11-11 18:55 UTC (permalink / raw) To: dev, david.hunt; +Cc: stable, alan.carew, pablo.de.lara.guarch This patch fixes the bug caused by improper use of buffered stdio file access for switching the CPU frequency and governor. When using buffered stdio, each fwrite() must use fflush() and the return code must be verified. Also fseek() is needed. Therefore it is better to use unbuffered mode or use plain open()/write() functions. This fix use second approach. This not only remove need for ffush() but also remove need for fseek() operations. This patch also reuse some code around power_set_governor_userspace() and power_set_governor_userspace() functions. Fixes: 445c6528b55f ("power: common interface for guest and host") CC: stable@dpdk.org Signed-off-by: Radoslaw Biernacki <radoslaw.biernacki@linaro.org> --- lib/librte_power/rte_power_acpi_cpufreq.c | 211 +++++++++++++----------------- 1 file changed, 91 insertions(+), 120 deletions(-) diff --git a/lib/librte_power/rte_power_acpi_cpufreq.c b/lib/librte_power/rte_power_acpi_cpufreq.c index 3d0872f..f811bd3 100644 --- a/lib/librte_power/rte_power_acpi_cpufreq.c +++ b/lib/librte_power/rte_power_acpi_cpufreq.c @@ -30,7 +30,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - +#include <assert.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> @@ -47,6 +47,12 @@ #include "rte_power_acpi_cpufreq.h" #include "rte_power_common.h" +#define min(_x, _y) ({ \ + typeof(_x) _min1 = (_x); \ + typeof(_y) _min2 = (_y); \ + (void) (&_min1 == &_min2); \ + _min1 < _min2 ? _min1 : _min2; }) + #ifdef RTE_LIBRTE_POWER_DEBUG #define POWER_DEBUG_TRACE(fmt, args...) do { \ RTE_LOG(ERR, POWER, "%s: " fmt, __func__, ## args); \ @@ -88,7 +94,7 @@ struct rte_power_info { unsigned lcore_id; /**< Logical core id */ uint32_t freqs[RTE_MAX_LCORE_FREQS]; /**< Frequency array */ uint32_t nb_freqs; /**< number of available freqs */ - FILE *f; /**< FD of scaling_setspeed */ + int fd; /**< FD of scaling_setspeed */ char governor_ori[32]; /**< Original governor name */ uint32_t curr_idx; /**< Freq index in freqs array */ volatile uint32_t state; /**< Power in use state */ @@ -105,6 +111,9 @@ static struct rte_power_info lcore_power_info[RTE_MAX_LCORE]; static int set_freq_internal(struct rte_power_info *pi, uint32_t idx) { + char buf[BUFSIZ]; + int count, ret; + if (idx >= RTE_MAX_LCORE_FREQS || idx >= pi->nb_freqs) { RTE_LOG(ERR, POWER, "Invalid frequency index %u, which " "should be less than %u\n", idx, pi->nb_freqs); @@ -117,17 +126,14 @@ set_freq_internal(struct rte_power_info *pi, uint32_t idx) POWER_DEBUG_TRACE("Freqency[%u] %u to be set for lcore %u\n", idx, pi->freqs[idx], pi->lcore_id); - if (fseek(pi->f, 0, SEEK_SET) < 0) { - RTE_LOG(ERR, POWER, "Fail to set file position indicator to 0 " - "for setting frequency for lcore %u\n", pi->lcore_id); + count = snprintf(buf, sizeof(buf), "%u", pi->freqs[idx]); + assert((size_t)count < sizeof(buf)-1); + ret = write(pi->fd, buf, count); + if (ret != count) { + RTE_LOG(ERR, POWER, "Fail to write new frequency (%s) for " + "lcore %u\n", buf, pi->lcore_id); return -1; } - if (fprintf(pi->f, "%u", pi->freqs[idx]) < 0) { - RTE_LOG(ERR, POWER, "Fail to write new frequency for " - "lcore %u\n", pi->lcore_id); - return -1; - } - fflush(pi->f); pi->curr_idx = idx; return 1; @@ -139,90 +145,109 @@ set_freq_internal(struct rte_power_info *pi, uint32_t idx) * governor will be saved for rolling back. */ static int -power_set_governor_userspace(struct rte_power_info *pi) +power_set_governor(unsigned int lcore_id, const char *new_gov, char *old_gov, + size_t old_gov_len) { - FILE *f; + int fd; + int count, len; int ret = -1; char buf[BUFSIZ]; char fullpath[PATH_MAX]; - char *s; - int val; snprintf(fullpath, sizeof(fullpath), POWER_SYSFILE_GOVERNOR, - pi->lcore_id); - f = fopen(fullpath, "rw+"); - if (!f) { + lcore_id); + fd = open(fullpath, O_RDWR); + if (fd < 0) { RTE_LOG(ERR, POWER, "Failed to open %s\n", fullpath); return ret; } - s = fgets(buf, sizeof(buf), f); - if (!s) { - RTE_LOG(ERR, POWER, "fgets returns nothing\n"); + count = read(fd, buf, sizeof(buf)); + if (count < 0) { + RTE_LOG(ERR, POWER, "Failed to read from %s\n", fullpath); goto out; } + buf[min((size_t)count, sizeof(buf)-1)] = '\0'; - /* Check if current governor is userspace */ - if (strncmp(buf, POWER_GOVERNOR_USERSPACE, - sizeof(POWER_GOVERNOR_USERSPACE)) == 0) { + /* Check if current governor is as requested */ + if (!strcmp(buf, new_gov)) { ret = 0; POWER_DEBUG_TRACE("Power management governor of lcore %u is " - "already userspace\n", pi->lcore_id); - goto out; - } - /* Save the original governor */ - snprintf(pi->governor_ori, sizeof(pi->governor_ori), "%s", buf); - - /* Write 'userspace' to the governor */ - val = fseek(f, 0, SEEK_SET); - if (val < 0) { - RTE_LOG(ERR, POWER, "fseek failed\n"); + "already %s\n", lcore_id, new_gov); goto out; } + /* Save the old governor */ + if (old_gov) + snprintf(old_gov, old_gov_len, "%s", buf); - val = fputs(POWER_GOVERNOR_USERSPACE, f); - if (val < 0) { - RTE_LOG(ERR, POWER, "fputs failed\n"); + /* Set new governor */ + len = strlen(new_gov); + count = write(fd, new_gov, len); + if (count != len) { + RTE_LOG(ERR, POWER, "Failed to set %s governor\n", new_gov); goto out; } ret = 0; RTE_LOG(INFO, POWER, "Power management governor of lcore %u has been " - "set to user space successfully\n", pi->lcore_id); + "set to user space successfully\n", lcore_id); out: - fclose(f); + if (close(fd)) + RTE_LOG(ERR, POWER, "Error while closing file %s\n", fullpath); return ret; } /** + * It is to check the current scaling governor by reading sys file, and then + * set it into 'userspace' if it is not by writing the sys file. The original + * governor will be saved for rolling back. + */ +static int +power_set_governor_userspace(struct rte_power_info *pi) +{ + return power_set_governor(pi->lcore_id, POWER_GOVERNOR_USERSPACE, + pi->governor_ori, sizeof(pi->governor_ori)); +} + +/** + * It is to check the governor and then set the original governor back if + * needed by writing the the sys file. + */ +static int +power_set_governor_original(struct rte_power_info *pi) +{ + return power_set_governor(pi->lcore_id, pi->governor_ori, NULL, 0); +} + +/** * It is to get the available frequencies of the specific lcore by reading the * sys file. */ static int power_get_available_freqs(struct rte_power_info *pi) { - FILE *f; + int fd; int ret = -1, i, count; char *p; char buf[BUFSIZ]; char fullpath[PATH_MAX]; char *freqs[RTE_MAX_LCORE_FREQS]; - char *s; snprintf(fullpath, sizeof(fullpath), POWER_SYSFILE_AVAIL_FREQ, - pi->lcore_id); - f = fopen(fullpath, "r"); - if (!f) { + pi->lcore_id); + fd = open(fullpath, O_RDONLY); + if (fd < 0) { RTE_LOG(ERR, POWER, "Failed to open %s\n", fullpath); return ret; } - s = fgets(buf, sizeof(buf), f); - if (!s) { - RTE_LOG(ERR, POWER, "fgets returns nothing\n"); + count = read(fd, buf, sizeof(buf)); + if (count < 0) { + RTE_LOG(ERR, POWER, "Failed to read from %s\n", fullpath); goto out; } + buf[min((size_t)count, sizeof(buf)-1)] = '\0'; /* Strip the line break if there is */ p = strchr(buf, '\n'); @@ -267,7 +292,8 @@ power_get_available_freqs(struct rte_power_info *pi) POWER_DEBUG_TRACE("%d frequencie(s) of lcore %u are available\n", count, pi->lcore_id); out: - fclose(f); + if (close(fd)) + RTE_LOG(ERR, POWER, "Error while closing file %s\n", fullpath); return ret; } @@ -278,37 +304,39 @@ power_get_available_freqs(struct rte_power_info *pi) static int power_init_for_setting_freq(struct rte_power_info *pi) { - FILE *f; + int fd; + int count; + uint32_t i, freq; char fullpath[PATH_MAX]; char buf[BUFSIZ]; - uint32_t i, freq; - char *s; snprintf(fullpath, sizeof(fullpath), POWER_SYSFILE_SETSPEED, pi->lcore_id); - f = fopen(fullpath, "rw+"); - if (!f) { + fd = open(fullpath, O_RDWR); + if (fd < 0) { RTE_LOG(ERR, POWER, "Failed to open %s\n", fullpath); return -1; } - s = fgets(buf, sizeof(buf), f); - if (!s) { - RTE_LOG(ERR, POWER, "fgets returns nothing\n"); + count = read(fd, buf, sizeof(buf)); + if (count < 0) { + RTE_LOG(ERR, POWER, "Failed to read from %s\n", fullpath); goto out; } + buf[min((size_t)count, sizeof(buf)-1)] = '\0'; freq = strtoul(buf, NULL, POWER_CONVERT_TO_DECIMAL); for (i = 0; i < pi->nb_freqs; i++) { if (freq == pi->freqs[i]) { pi->curr_idx = i; - pi->f = f; + pi->fd = fd; return 0; } } out: - fclose(f); + if (close(fd)) + RTE_LOG(ERR, POWER, "Error while closing file %s\n", fullpath); return -1; } @@ -373,66 +401,6 @@ rte_power_acpi_cpufreq_init(unsigned lcore_id) return -1; } -/** - * It is to check the governor and then set the original governor back if - * needed by writing the the sys file. - */ -static int -power_set_governor_original(struct rte_power_info *pi) -{ - FILE *f; - int ret = -1; - char buf[BUFSIZ]; - char fullpath[PATH_MAX]; - char *s; - int val; - - snprintf(fullpath, sizeof(fullpath), POWER_SYSFILE_GOVERNOR, - pi->lcore_id); - f = fopen(fullpath, "rw+"); - if (!f) { - RTE_LOG(ERR, POWER, "Failed to open %s\n", fullpath); - return ret; - } - - s = fgets(buf, sizeof(buf), f); - if (!s) { - RTE_LOG(ERR, POWER, "fgets returns nothing\n"); - goto out; - } - - /* Check if the governor to be set is the same as current */ - if (strncmp(buf, pi->governor_ori, sizeof(pi->governor_ori)) == 0) { - ret = 0; - POWER_DEBUG_TRACE("Power management governor of lcore %u " - "has already been set to %s\n", - pi->lcore_id, pi->governor_ori); - goto out; - } - - /* Write back the original governor */ - val = fseek(f, 0, SEEK_SET); - if (val < 0) { - RTE_LOG(ERR, POWER, "fseek failed\n"); - goto out; - } - - val = fputs(pi->governor_ori, f); - if (val < 0) { - RTE_LOG(ERR, POWER, "fputs failed\n"); - goto out; - } - - ret = 0; - RTE_LOG(INFO, POWER, "Power management governor of lcore %u " - "has been set back to %s successfully\n", - pi->lcore_id, pi->governor_ori); -out: - fclose(f); - - return ret; -} - int rte_power_acpi_cpufreq_exit(unsigned lcore_id) { @@ -452,8 +420,11 @@ rte_power_acpi_cpufreq_exit(unsigned lcore_id) } /* Close FD of setting freq */ - fclose(pi->f); - pi->f = NULL; + if (close(pi->fd)) { + RTE_LOG(ERR, POWER, "Error while closing governor file\n"); + return -1; + } + pi->fd = -1; /* Set the governor back to the original */ if (power_set_governor_original(pi) < 0) { -- 2.7.4 ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [dpdk-dev] [PATCH 2/3] power: switching to unbuffered access for /sys files 2017-11-11 18:55 ` [dpdk-dev] [PATCH 2/3] power: switching to unbuffered access for /sys files Radoslaw Biernacki @ 2017-11-23 14:42 ` Hunt, David 2017-12-01 21:01 ` Radoslaw Biernacki 0 siblings, 1 reply; 15+ messages in thread From: Hunt, David @ 2017-11-23 14:42 UTC (permalink / raw) To: Radoslaw Biernacki, dev; +Cc: stable, alan.carew, pablo.de.lara.guarch Hi Radoslaw, On 11/11/2017 6:55 PM, Radoslaw Biernacki wrote: > This patch fixes the bug caused by improper use of buffered stdio file > access for switching the CPU frequency and governor. When using > buffered stdio, each fwrite() must use fflush() and the return code > must be verified. Also fseek() is needed. Therefore it is better to > use unbuffered mode or use plain open()/write() functions. This fix > use second approach. This not only remove need for ffush() but also > remove need for fseek() operations. This patch also reuse some code > around power_set_governor_userspace() and > power_set_governor_userspace() functions. > > Fixes: 445c6528b55f ("power: common interface for guest and host") > CC: stable@dpdk.org > > Signed-off-by: Radoslaw Biernacki <radoslaw.biernacki@linaro.org> > --- > lib/librte_power/rte_power_acpi_cpufreq.c | 211 +++++++++++++----------------- > 1 file changed, 91 insertions(+), 120 deletions(-) > > diff --git a/lib/librte_power/rte_power_acpi_cpufreq.c b/lib/librte_power/rte_power_acpi_cpufreq.c > index 3d0872f..f811bd3 100644 > --- a/lib/librte_power/rte_power_acpi_cpufreq.c > +++ b/lib/librte_power/rte_power_acpi_cpufreq.c > @@ -30,7 +30,7 @@ > * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE > * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > */ > - > +#include <assert.h> > #include <stdio.h> > #include <sys/types.h> > #include <sys/stat.h> > @@ -47,6 +47,12 @@ > #include "rte_power_acpi_cpufreq.h" > #include "rte_power_common.h" > > +#define min(_x, _y) ({ \ > + typeof(_x) _min1 = (_x); \ > + typeof(_y) _min2 = (_y); \ > + (void) (&_min1 == &_min2); \ > + _min1 < _min2 ? _min1 : _min2; }) > + > #ifdef RTE_LIBRTE_POWER_DEBUG > #define POWER_DEBUG_TRACE(fmt, args...) do { \ > RTE_LOG(ERR, POWER, "%s: " fmt, __func__, ## args); \ > @@ -88,7 +94,7 @@ struct rte_power_info { > unsigned lcore_id; /**< Logical core id */ > uint32_t freqs[RTE_MAX_LCORE_FREQS]; /**< Frequency array */ > uint32_t nb_freqs; /**< number of available freqs */ > - FILE *f; /**< FD of scaling_setspeed */ > + int fd; /**< FD of scaling_setspeed */ > char governor_ori[32]; /**< Original governor name */ > uint32_t curr_idx; /**< Freq index in freqs array */ > volatile uint32_t state; /**< Power in use state */ > @@ -105,6 +111,9 @@ static struct rte_power_info lcore_power_info[RTE_MAX_LCORE]; > static int > set_freq_internal(struct rte_power_info *pi, uint32_t idx) > { > + char buf[BUFSIZ]; > + int count, ret; > + > if (idx >= RTE_MAX_LCORE_FREQS || idx >= pi->nb_freqs) { > RTE_LOG(ERR, POWER, "Invalid frequency index %u, which " > "should be less than %u\n", idx, pi->nb_freqs); > @@ -117,17 +126,14 @@ set_freq_internal(struct rte_power_info *pi, uint32_t idx) > > POWER_DEBUG_TRACE("Freqency[%u] %u to be set for lcore %u\n", > idx, pi->freqs[idx], pi->lcore_id); > - if (fseek(pi->f, 0, SEEK_SET) < 0) { > - RTE_LOG(ERR, POWER, "Fail to set file position indicator to 0 " > - "for setting frequency for lcore %u\n", pi->lcore_id); > + count = snprintf(buf, sizeof(buf), "%u", pi->freqs[idx]); > + assert((size_t)count < sizeof(buf)-1); > + ret = write(pi->fd, buf, count); > + if (ret != count) { > + RTE_LOG(ERR, POWER, "Fail to write new frequency (%s) for " > + "lcore %u\n", buf, pi->lcore_id); > return -1; > } > - if (fprintf(pi->f, "%u", pi->freqs[idx]) < 0) { > - RTE_LOG(ERR, POWER, "Fail to write new frequency for " > - "lcore %u\n", pi->lcore_id); > - return -1; > - } > - fflush(pi->f); > pi->curr_idx = idx; > > return 1; > @@ -139,90 +145,109 @@ set_freq_internal(struct rte_power_info *pi, uint32_t idx) > * governor will be saved for rolling back. > */ > static int > -power_set_governor_userspace(struct rte_power_info *pi) > +power_set_governor(unsigned int lcore_id, const char *new_gov, char *old_gov, > + size_t old_gov_len) > { > - FILE *f; > + int fd; > + int count, len; > int ret = -1; > char buf[BUFSIZ]; > char fullpath[PATH_MAX]; > - char *s; > - int val; > > snprintf(fullpath, sizeof(fullpath), POWER_SYSFILE_GOVERNOR, > - pi->lcore_id); > - f = fopen(fullpath, "rw+"); > - if (!f) { > + lcore_id); > + fd = open(fullpath, O_RDWR); > + if (fd < 0) { > RTE_LOG(ERR, POWER, "Failed to open %s\n", fullpath); > return ret; > } > > - s = fgets(buf, sizeof(buf), f); > - if (!s) { > - RTE_LOG(ERR, POWER, "fgets returns nothing\n"); > + count = read(fd, buf, sizeof(buf)); > + if (count < 0) { > + RTE_LOG(ERR, POWER, "Failed to read from %s\n", fullpath); > goto out; > } > + buf[min((size_t)count, sizeof(buf)-1)] = '\0'; > > - /* Check if current governor is userspace */ > - if (strncmp(buf, POWER_GOVERNOR_USERSPACE, > - sizeof(POWER_GOVERNOR_USERSPACE)) == 0) { > + /* Check if current governor is as requested */ > + if (!strcmp(buf, new_gov)) { > ret = 0; > POWER_DEBUG_TRACE("Power management governor of lcore %u is " > - "already userspace\n", pi->lcore_id); > - goto out; > - } > - /* Save the original governor */ > - snprintf(pi->governor_ori, sizeof(pi->governor_ori), "%s", buf); > - > - /* Write 'userspace' to the governor */ > - val = fseek(f, 0, SEEK_SET); > - if (val < 0) { > - RTE_LOG(ERR, POWER, "fseek failed\n"); > + "already %s\n", lcore_id, new_gov); > goto out; > } > + /* Save the old governor */ > + if (old_gov) > + snprintf(old_gov, old_gov_len, "%s", buf); > > - val = fputs(POWER_GOVERNOR_USERSPACE, f); > - if (val < 0) { > - RTE_LOG(ERR, POWER, "fputs failed\n"); > + /* Set new governor */ > + len = strlen(new_gov); > + count = write(fd, new_gov, len); > + if (count != len) { > + RTE_LOG(ERR, POWER, "Failed to set %s governor\n", new_gov); > goto out; > } > > ret = 0; > RTE_LOG(INFO, POWER, "Power management governor of lcore %u has been " > - "set to user space successfully\n", pi->lcore_id); > + "set to user space successfully\n", lcore_id); > out: > - fclose(f); > + if (close(fd)) > + RTE_LOG(ERR, POWER, "Error while closing file %s\n", fullpath); > > return ret; > } > > /** > + * It is to check the current scaling governor by reading sys file, and then > + * set it into 'userspace' if it is not by writing the sys file. The original > + * governor will be saved for rolling back. > + */ > +static int > +power_set_governor_userspace(struct rte_power_info *pi) > +{ > + return power_set_governor(pi->lcore_id, POWER_GOVERNOR_USERSPACE, > + pi->governor_ori, sizeof(pi->governor_ori)); > +} > + > +/** > + * It is to check the governor and then set the original governor back if > + * needed by writing the the sys file. > + */ > +static int > +power_set_governor_original(struct rte_power_info *pi) > +{ > + return power_set_governor(pi->lcore_id, pi->governor_ori, NULL, 0); > +} > + > +/** > * It is to get the available frequencies of the specific lcore by reading the > * sys file. > */ > static int > power_get_available_freqs(struct rte_power_info *pi) > { > - FILE *f; > + int fd; > int ret = -1, i, count; > char *p; > char buf[BUFSIZ]; > char fullpath[PATH_MAX]; > char *freqs[RTE_MAX_LCORE_FREQS]; > - char *s; > > snprintf(fullpath, sizeof(fullpath), POWER_SYSFILE_AVAIL_FREQ, > - pi->lcore_id); > - f = fopen(fullpath, "r"); > - if (!f) { > + pi->lcore_id); > + fd = open(fullpath, O_RDONLY); > + if (fd < 0) { > RTE_LOG(ERR, POWER, "Failed to open %s\n", fullpath); > return ret; > } > > - s = fgets(buf, sizeof(buf), f); > - if (!s) { > - RTE_LOG(ERR, POWER, "fgets returns nothing\n"); > + count = read(fd, buf, sizeof(buf)); > + if (count < 0) { > + RTE_LOG(ERR, POWER, "Failed to read from %s\n", fullpath); > goto out; > } > + buf[min((size_t)count, sizeof(buf)-1)] = '\0'; > > /* Strip the line break if there is */ > p = strchr(buf, '\n'); > @@ -267,7 +292,8 @@ power_get_available_freqs(struct rte_power_info *pi) > POWER_DEBUG_TRACE("%d frequencie(s) of lcore %u are available\n", > count, pi->lcore_id); > out: > - fclose(f); > + if (close(fd)) > + RTE_LOG(ERR, POWER, "Error while closing file %s\n", fullpath); > > return ret; > } > @@ -278,37 +304,39 @@ power_get_available_freqs(struct rte_power_info *pi) > static int > power_init_for_setting_freq(struct rte_power_info *pi) > { > - FILE *f; > + int fd; > + int count; > + uint32_t i, freq; > char fullpath[PATH_MAX]; > char buf[BUFSIZ]; > - uint32_t i, freq; > - char *s; > > snprintf(fullpath, sizeof(fullpath), POWER_SYSFILE_SETSPEED, > pi->lcore_id); > - f = fopen(fullpath, "rw+"); > - if (!f) { > + fd = open(fullpath, O_RDWR); > + if (fd < 0) { > RTE_LOG(ERR, POWER, "Failed to open %s\n", fullpath); > return -1; > } > > - s = fgets(buf, sizeof(buf), f); > - if (!s) { > - RTE_LOG(ERR, POWER, "fgets returns nothing\n"); > + count = read(fd, buf, sizeof(buf)); > + if (count < 0) { > + RTE_LOG(ERR, POWER, "Failed to read from %s\n", fullpath); > goto out; > } > + buf[min((size_t)count, sizeof(buf)-1)] = '\0'; > > freq = strtoul(buf, NULL, POWER_CONVERT_TO_DECIMAL); > for (i = 0; i < pi->nb_freqs; i++) { > if (freq == pi->freqs[i]) { > pi->curr_idx = i; > - pi->f = f; > + pi->fd = fd; > return 0; > } > } > > out: > - fclose(f); > + if (close(fd)) > + RTE_LOG(ERR, POWER, "Error while closing file %s\n", fullpath); > > return -1; > } > @@ -373,66 +401,6 @@ rte_power_acpi_cpufreq_init(unsigned lcore_id) > return -1; > } > > -/** > - * It is to check the governor and then set the original governor back if > - * needed by writing the the sys file. > - */ > -static int > -power_set_governor_original(struct rte_power_info *pi) > -{ > - FILE *f; > - int ret = -1; > - char buf[BUFSIZ]; > - char fullpath[PATH_MAX]; > - char *s; > - int val; > - > - snprintf(fullpath, sizeof(fullpath), POWER_SYSFILE_GOVERNOR, > - pi->lcore_id); > - f = fopen(fullpath, "rw+"); > - if (!f) { > - RTE_LOG(ERR, POWER, "Failed to open %s\n", fullpath); > - return ret; > - } > - > - s = fgets(buf, sizeof(buf), f); > - if (!s) { > - RTE_LOG(ERR, POWER, "fgets returns nothing\n"); > - goto out; > - } > - > - /* Check if the governor to be set is the same as current */ > - if (strncmp(buf, pi->governor_ori, sizeof(pi->governor_ori)) == 0) { > - ret = 0; > - POWER_DEBUG_TRACE("Power management governor of lcore %u " > - "has already been set to %s\n", > - pi->lcore_id, pi->governor_ori); > - goto out; > - } > - > - /* Write back the original governor */ > - val = fseek(f, 0, SEEK_SET); > - if (val < 0) { > - RTE_LOG(ERR, POWER, "fseek failed\n"); > - goto out; > - } > - > - val = fputs(pi->governor_ori, f); > - if (val < 0) { > - RTE_LOG(ERR, POWER, "fputs failed\n"); > - goto out; > - } > - > - ret = 0; > - RTE_LOG(INFO, POWER, "Power management governor of lcore %u " > - "has been set back to %s successfully\n", > - pi->lcore_id, pi->governor_ori); > -out: > - fclose(f); > - > - return ret; > -} > - > int > rte_power_acpi_cpufreq_exit(unsigned lcore_id) > { > @@ -452,8 +420,11 @@ rte_power_acpi_cpufreq_exit(unsigned lcore_id) > } > > /* Close FD of setting freq */ > - fclose(pi->f); > - pi->f = NULL; > + if (close(pi->fd)) { > + RTE_LOG(ERR, POWER, "Error while closing governor file\n"); > + return -1; > + } > + pi->fd = -1; > > /* Set the governor back to the original */ > if (power_set_governor_original(pi) < 0) { Could you re-base on top of 17.11? It fails to apply currently. I think there is a little much going on in this patch, there are a couple of discreet changes that could/should be split into individual patches. Your first patch in this series does this well, remove the macros. I think this one could be split into two patches: 1. First the switch to unbuffered file access, including the extra error checking. 2. Then rework the functions, i.e. add the new "power_set_governor" function and have "_userspace" and "_original" call that. Do you agree? Regards, Dave ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [dpdk-dev] [PATCH 2/3] power: switching to unbuffered access for /sys files 2017-11-23 14:42 ` Hunt, David @ 2017-12-01 21:01 ` Radoslaw Biernacki 2018-01-31 23:38 ` [dpdk-dev] [dpdk-stable] " Thomas Monjalon 0 siblings, 1 reply; 15+ messages in thread From: Radoslaw Biernacki @ 2017-12-01 21:01 UTC (permalink / raw) To: Hunt, David; +Cc: dev, stable, alan.carew, pablo.de.lara.guarch Hi David, Sorry for log delay. I will make V3 with your suggestions. Thanks. On 23 November 2017 at 15:42, Hunt, David <david.hunt@intel.com> wrote: > Hi Radoslaw, > > > > On 11/11/2017 6:55 PM, Radoslaw Biernacki wrote: > >> This patch fixes the bug caused by improper use of buffered stdio file >> access for switching the CPU frequency and governor. When using >> buffered stdio, each fwrite() must use fflush() and the return code >> must be verified. Also fseek() is needed. Therefore it is better to >> use unbuffered mode or use plain open()/write() functions. This fix >> use second approach. This not only remove need for ffush() but also >> remove need for fseek() operations. This patch also reuse some code >> around power_set_governor_userspace() and >> power_set_governor_userspace() functions. >> >> Fixes: 445c6528b55f ("power: common interface for guest and host") >> CC: stable@dpdk.org >> >> Signed-off-by: Radoslaw Biernacki <radoslaw.biernacki@linaro.org> >> --- >> lib/librte_power/rte_power_acpi_cpufreq.c | 211 >> +++++++++++++----------------- >> 1 file changed, 91 insertions(+), 120 deletions(-) >> >> diff --git a/lib/librte_power/rte_power_acpi_cpufreq.c >> b/lib/librte_power/rte_power_acpi_cpufreq.c >> index 3d0872f..f811bd3 100644 >> --- a/lib/librte_power/rte_power_acpi_cpufreq.c >> +++ b/lib/librte_power/rte_power_acpi_cpufreq.c >> @@ -30,7 +30,7 @@ >> * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE >> USE >> * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH >> DAMAGE. >> */ >> - >> +#include <assert.h> >> #include <stdio.h> >> #include <sys/types.h> >> #include <sys/stat.h> >> @@ -47,6 +47,12 @@ >> #include "rte_power_acpi_cpufreq.h" >> #include "rte_power_common.h" >> +#define min(_x, _y) ({ \ >> + typeof(_x) _min1 = (_x); \ >> + typeof(_y) _min2 = (_y); \ >> + (void) (&_min1 == &_min2); \ >> + _min1 < _min2 ? _min1 : _min2; }) >> + >> #ifdef RTE_LIBRTE_POWER_DEBUG >> #define POWER_DEBUG_TRACE(fmt, args...) do { \ >> RTE_LOG(ERR, POWER, "%s: " fmt, __func__, ## args); \ >> @@ -88,7 +94,7 @@ struct rte_power_info { >> unsigned lcore_id; /**< Logical core id */ >> uint32_t freqs[RTE_MAX_LCORE_FREQS]; /**< Frequency array */ >> uint32_t nb_freqs; /**< number of available >> freqs */ >> - FILE *f; /**< FD of scaling_setspeed >> */ >> + int fd; /**< FD of scaling_setspeed >> */ >> char governor_ori[32]; /**< Original governor name >> */ >> uint32_t curr_idx; /**< Freq index in freqs >> array */ >> volatile uint32_t state; /**< Power in use state */ >> @@ -105,6 +111,9 @@ static struct rte_power_info >> lcore_power_info[RTE_MAX_LCORE]; >> static int >> set_freq_internal(struct rte_power_info *pi, uint32_t idx) >> { >> + char buf[BUFSIZ]; >> + int count, ret; >> + >> if (idx >= RTE_MAX_LCORE_FREQS || idx >= pi->nb_freqs) { >> RTE_LOG(ERR, POWER, "Invalid frequency index %u, which " >> "should be less than %u\n", idx, >> pi->nb_freqs); >> @@ -117,17 +126,14 @@ set_freq_internal(struct rte_power_info *pi, >> uint32_t idx) >> POWER_DEBUG_TRACE("Freqency[%u] %u to be set for lcore %u\n", >> idx, pi->freqs[idx], pi->lcore_id); >> - if (fseek(pi->f, 0, SEEK_SET) < 0) { >> - RTE_LOG(ERR, POWER, "Fail to set file position indicator >> to 0 " >> - "for setting frequency for lcore %u\n", >> pi->lcore_id); >> + count = snprintf(buf, sizeof(buf), "%u", pi->freqs[idx]); >> + assert((size_t)count < sizeof(buf)-1); >> + ret = write(pi->fd, buf, count); >> + if (ret != count) { >> + RTE_LOG(ERR, POWER, "Fail to write new frequency (%s) for >> " >> + "lcore %u\n", buf, pi->lcore_id); >> return -1; >> } >> - if (fprintf(pi->f, "%u", pi->freqs[idx]) < 0) { >> - RTE_LOG(ERR, POWER, "Fail to write new frequency for " >> - "lcore %u\n", pi->lcore_id); >> - return -1; >> - } >> - fflush(pi->f); >> pi->curr_idx = idx; >> return 1; >> @@ -139,90 +145,109 @@ set_freq_internal(struct rte_power_info *pi, >> uint32_t idx) >> * governor will be saved for rolling back. >> */ >> static int >> -power_set_governor_userspace(struct rte_power_info *pi) >> +power_set_governor(unsigned int lcore_id, const char *new_gov, char >> *old_gov, >> + size_t old_gov_len) >> { >> - FILE *f; >> + int fd; >> + int count, len; >> int ret = -1; >> char buf[BUFSIZ]; >> char fullpath[PATH_MAX]; >> - char *s; >> - int val; >> snprintf(fullpath, sizeof(fullpath), POWER_SYSFILE_GOVERNOR, >> - pi->lcore_id); >> - f = fopen(fullpath, "rw+"); >> - if (!f) { >> + lcore_id); >> + fd = open(fullpath, O_RDWR); >> + if (fd < 0) { >> RTE_LOG(ERR, POWER, "Failed to open %s\n", fullpath); >> return ret; >> } >> - s = fgets(buf, sizeof(buf), f); >> - if (!s) { >> - RTE_LOG(ERR, POWER, "fgets returns nothing\n"); >> + count = read(fd, buf, sizeof(buf)); >> + if (count < 0) { >> + RTE_LOG(ERR, POWER, "Failed to read from %s\n", fullpath); >> goto out; >> } >> + buf[min((size_t)count, sizeof(buf)-1)] = '\0'; >> - /* Check if current governor is userspace */ >> - if (strncmp(buf, POWER_GOVERNOR_USERSPACE, >> - sizeof(POWER_GOVERNOR_USERSPACE)) == 0) { >> + /* Check if current governor is as requested */ >> + if (!strcmp(buf, new_gov)) { >> ret = 0; >> POWER_DEBUG_TRACE("Power management governor of lcore %u >> is " >> - "already userspace\n", pi->lcore_id); >> - goto out; >> - } >> - /* Save the original governor */ >> - snprintf(pi->governor_ori, sizeof(pi->governor_ori), "%s", buf); >> - >> - /* Write 'userspace' to the governor */ >> - val = fseek(f, 0, SEEK_SET); >> - if (val < 0) { >> - RTE_LOG(ERR, POWER, "fseek failed\n"); >> + "already %s\n", lcore_id, new_gov); >> goto out; >> } >> + /* Save the old governor */ >> + if (old_gov) >> + snprintf(old_gov, old_gov_len, "%s", buf); >> - val = fputs(POWER_GOVERNOR_USERSPACE, f); >> - if (val < 0) { >> - RTE_LOG(ERR, POWER, "fputs failed\n"); >> + /* Set new governor */ >> + len = strlen(new_gov); >> + count = write(fd, new_gov, len); >> + if (count != len) { >> + RTE_LOG(ERR, POWER, "Failed to set %s governor\n", >> new_gov); >> goto out; >> } >> ret = 0; >> RTE_LOG(INFO, POWER, "Power management governor of lcore %u has >> been " >> - "set to user space successfully\n", pi->lcore_id); >> + "set to user space successfully\n", lcore_id); >> out: >> - fclose(f); >> + if (close(fd)) >> + RTE_LOG(ERR, POWER, "Error while closing file %s\n", >> fullpath); >> return ret; >> } >> /** >> + * It is to check the current scaling governor by reading sys file, and >> then >> + * set it into 'userspace' if it is not by writing the sys file. The >> original >> + * governor will be saved for rolling back. >> + */ >> +static int >> +power_set_governor_userspace(struct rte_power_info *pi) >> +{ >> + return power_set_governor(pi->lcore_id, POWER_GOVERNOR_USERSPACE, >> + pi->governor_ori, >> sizeof(pi->governor_ori)); >> +} >> + >> +/** >> + * It is to check the governor and then set the original governor back if >> + * needed by writing the the sys file. >> + */ >> +static int >> +power_set_governor_original(struct rte_power_info *pi) >> +{ >> + return power_set_governor(pi->lcore_id, pi->governor_ori, NULL, >> 0); >> +} >> + >> +/** >> * It is to get the available frequencies of the specific lcore by >> reading the >> * sys file. >> */ >> static int >> power_get_available_freqs(struct rte_power_info *pi) >> { >> - FILE *f; >> + int fd; >> int ret = -1, i, count; >> char *p; >> char buf[BUFSIZ]; >> char fullpath[PATH_MAX]; >> char *freqs[RTE_MAX_LCORE_FREQS]; >> - char *s; >> snprintf(fullpath, sizeof(fullpath), POWER_SYSFILE_AVAIL_FREQ, >> - pi->lcore_id); >> - f = fopen(fullpath, "r"); >> - if (!f) { >> + pi->lcore_id); >> + fd = open(fullpath, O_RDONLY); >> + if (fd < 0) { >> RTE_LOG(ERR, POWER, "Failed to open %s\n", fullpath); >> return ret; >> } >> - s = fgets(buf, sizeof(buf), f); >> - if (!s) { >> - RTE_LOG(ERR, POWER, "fgets returns nothing\n"); >> + count = read(fd, buf, sizeof(buf)); >> + if (count < 0) { >> + RTE_LOG(ERR, POWER, "Failed to read from %s\n", fullpath); >> goto out; >> } >> + buf[min((size_t)count, sizeof(buf)-1)] = '\0'; >> /* Strip the line break if there is */ >> p = strchr(buf, '\n'); >> @@ -267,7 +292,8 @@ power_get_available_freqs(struct rte_power_info *pi) >> POWER_DEBUG_TRACE("%d frequencie(s) of lcore %u are available\n", >> count, pi->lcore_id); >> out: >> - fclose(f); >> + if (close(fd)) >> + RTE_LOG(ERR, POWER, "Error while closing file %s\n", >> fullpath); >> return ret; >> } >> @@ -278,37 +304,39 @@ power_get_available_freqs(struct rte_power_info >> *pi) >> static int >> power_init_for_setting_freq(struct rte_power_info *pi) >> { >> - FILE *f; >> + int fd; >> + int count; >> + uint32_t i, freq; >> char fullpath[PATH_MAX]; >> char buf[BUFSIZ]; >> - uint32_t i, freq; >> - char *s; >> snprintf(fullpath, sizeof(fullpath), POWER_SYSFILE_SETSPEED, >> pi->lcore_id); >> - f = fopen(fullpath, "rw+"); >> - if (!f) { >> + fd = open(fullpath, O_RDWR); >> + if (fd < 0) { >> RTE_LOG(ERR, POWER, "Failed to open %s\n", fullpath); >> return -1; >> } >> - s = fgets(buf, sizeof(buf), f); >> - if (!s) { >> - RTE_LOG(ERR, POWER, "fgets returns nothing\n"); >> + count = read(fd, buf, sizeof(buf)); >> + if (count < 0) { >> + RTE_LOG(ERR, POWER, "Failed to read from %s\n", fullpath); >> goto out; >> } >> + buf[min((size_t)count, sizeof(buf)-1)] = '\0'; >> freq = strtoul(buf, NULL, POWER_CONVERT_TO_DECIMAL); >> for (i = 0; i < pi->nb_freqs; i++) { >> if (freq == pi->freqs[i]) { >> pi->curr_idx = i; >> - pi->f = f; >> + pi->fd = fd; >> return 0; >> } >> } >> out: >> - fclose(f); >> + if (close(fd)) >> + RTE_LOG(ERR, POWER, "Error while closing file %s\n", >> fullpath); >> return -1; >> } >> @@ -373,66 +401,6 @@ rte_power_acpi_cpufreq_init(unsigned lcore_id) >> return -1; >> } >> -/** >> - * It is to check the governor and then set the original governor back if >> - * needed by writing the the sys file. >> - */ >> -static int >> -power_set_governor_original(struct rte_power_info *pi) >> -{ >> - FILE *f; >> - int ret = -1; >> - char buf[BUFSIZ]; >> - char fullpath[PATH_MAX]; >> - char *s; >> - int val; >> - >> - snprintf(fullpath, sizeof(fullpath), POWER_SYSFILE_GOVERNOR, >> - pi->lcore_id); >> - f = fopen(fullpath, "rw+"); >> - if (!f) { >> - RTE_LOG(ERR, POWER, "Failed to open %s\n", fullpath); >> - return ret; >> - } >> - >> - s = fgets(buf, sizeof(buf), f); >> - if (!s) { >> - RTE_LOG(ERR, POWER, "fgets returns nothing\n"); >> - goto out; >> - } >> - >> - /* Check if the governor to be set is the same as current */ >> - if (strncmp(buf, pi->governor_ori, sizeof(pi->governor_ori)) == >> 0) { >> - ret = 0; >> - POWER_DEBUG_TRACE("Power management governor of lcore %u " >> - "has already been set to %s\n", >> - pi->lcore_id, pi->governor_ori); >> - goto out; >> - } >> - >> - /* Write back the original governor */ >> - val = fseek(f, 0, SEEK_SET); >> - if (val < 0) { >> - RTE_LOG(ERR, POWER, "fseek failed\n"); >> - goto out; >> - } >> - >> - val = fputs(pi->governor_ori, f); >> - if (val < 0) { >> - RTE_LOG(ERR, POWER, "fputs failed\n"); >> - goto out; >> - } >> - >> - ret = 0; >> - RTE_LOG(INFO, POWER, "Power management governor of lcore %u " >> - "has been set back to %s successfully\n", >> - pi->lcore_id, pi->governor_ori); >> -out: >> - fclose(f); >> - >> - return ret; >> -} >> - >> int >> rte_power_acpi_cpufreq_exit(unsigned lcore_id) >> { >> @@ -452,8 +420,11 @@ rte_power_acpi_cpufreq_exit(unsigned lcore_id) >> } >> /* Close FD of setting freq */ >> - fclose(pi->f); >> - pi->f = NULL; >> + if (close(pi->fd)) { >> + RTE_LOG(ERR, POWER, "Error while closing governor >> file\n"); >> + return -1; >> + } >> + pi->fd = -1; >> /* Set the governor back to the original */ >> if (power_set_governor_original(pi) < 0) { >> > > Could you re-base on top of 17.11? It fails to apply currently. > > I think there is a little much going on in this patch, there are a couple > of discreet changes that could/should be split into individual patches. > Your first patch in this series does this well, remove the macros. > I think this one could be split into two patches: > 1. First the switch to unbuffered file access, including the extra > error checking. > 2. Then rework the functions, i.e. add the new "power_set_governor" > function and have "_userspace" and "_original" call that. > Do you agree? > Regards, > Dave > > ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [dpdk-dev] [dpdk-stable] [PATCH 2/3] power: switching to unbuffered access for /sys files 2017-12-01 21:01 ` Radoslaw Biernacki @ 2018-01-31 23:38 ` Thomas Monjalon 0 siblings, 0 replies; 15+ messages in thread From: Thomas Monjalon @ 2018-01-31 23:38 UTC (permalink / raw) To: Radoslaw Biernacki; +Cc: Hunt, David, dev, alan.carew, pablo.de.lara.guarch 01/12/2017 22:01, Radoslaw Biernacki: > Hi David, > > Sorry for log delay. > I will make V3 with your suggestions. > Thanks. Hi, Any news? ^ permalink raw reply [flat|nested] 15+ messages in thread
* [dpdk-dev] [PATCH 3/3] power: check if userspace governor is available 2017-11-11 18:55 ` [dpdk-dev] [PATCH 0/3] power: fixes for power ACPI through sysfs Radoslaw Biernacki 2017-11-11 18:55 ` [dpdk-dev] [PATCH 1/3] power: removing code macros Radoslaw Biernacki 2017-11-11 18:55 ` [dpdk-dev] [PATCH 2/3] power: switching to unbuffered access for /sys files Radoslaw Biernacki @ 2017-11-11 18:55 ` Radoslaw Biernacki 2017-11-21 11:09 ` [dpdk-dev] [PATCH 0/3] power: fixes for power ACPI through sysfs Radoslaw Biernacki 3 siblings, 0 replies; 15+ messages in thread From: Radoslaw Biernacki @ 2017-11-11 18:55 UTC (permalink / raw) To: dev, david.hunt; +Cc: stable, alan.carew, pablo.de.lara.guarch Since for new Intel CPU's kernel use intel_pstate driver, which does not offer userspace governor, it is wise to check the userspace governor availability before trying to perform governor switch. The outcome from this patch is direct information for user about the root cause of failure during the rte_power_acpi_cpufreq_init(). Signed-off-by: Radoslaw Biernacki <radoslaw.biernacki@linaro.org> --- lib/librte_power/rte_power_acpi_cpufreq.c | 74 +++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/lib/librte_power/rte_power_acpi_cpufreq.c b/lib/librte_power/rte_power_acpi_cpufreq.c index f811bd3..0d9a2a5 100644 --- a/lib/librte_power/rte_power_acpi_cpufreq.c +++ b/lib/librte_power/rte_power_acpi_cpufreq.c @@ -65,6 +65,11 @@ #define POWER_CONVERT_TO_DECIMAL 10 #define POWER_GOVERNOR_USERSPACE "userspace" +#define POWER_SCALING_DRIVER_INTEL_PSTATE "intel_pstate" +#define POWER_SYSFILE_SCALING_DRIVER \ + "/sys/devices/system/cpu/cpu%u/cpufreq/scaling_driver" +#define POWER_SYSFILE_AVAIL_GOVERNOR \ + "/sys/devices/system/cpu/cpu%u/cpufreq/scaling_available_governors" #define POWER_SYSFILE_GOVERNOR \ "/sys/devices/system/cpu/cpu%u/cpufreq/scaling_governor" #define POWER_SYSFILE_AVAIL_FREQ \ @@ -139,6 +144,70 @@ set_freq_internal(struct rte_power_info *pi, uint32_t idx) return 1; } +/* check /sys file for presence of given string */ +static int +power_check_sysfile_string(const char *fullpath, const char *string) +{ + int fd; + int count; + int ret = -1; + char buf[BUFSIZ]; + + fd = open(fullpath, O_RDONLY); + if (fd < 0) { + RTE_LOG(ERR, POWER, "Failed to open %s\n", fullpath); + return ret; + } + + count = read(fd, buf, sizeof(buf)); + if (count < 0) { + RTE_LOG(ERR, POWER, "Failed to read from %s\n", fullpath); + goto out; + } + buf[min((size_t)count, sizeof(buf)-1)] = '\0'; + + if (strstr(buf, string)) + ret = 0; /* substring found */ + +out: + if (close(fd)) { + RTE_LOG(ERR, POWER, "Error while closing file %s\n", fullpath); + return -1; + } + + return ret; +} + +/* check if userspace governor is offered by the kernel */ +static int power_check_gov_userspace(unsigned int lcore_id) +{ + char fullpath[PATH_MAX]; + + snprintf(fullpath, sizeof(fullpath), + POWER_SYSFILE_AVAIL_GOVERNOR, lcore_id); + if (power_check_sysfile_string( + fullpath, POWER_GOVERNOR_USERSPACE)) { + + RTE_LOG(ERR, POWER, "Userspace governor is not available\n"); + + snprintf(fullpath, sizeof(fullpath), + POWER_SYSFILE_SCALING_DRIVER, lcore_id); + if (!power_check_sysfile_string( + fullpath, POWER_SCALING_DRIVER_INTEL_PSTATE)) { + + RTE_LOG(WARNING, POWER, + POWER_SCALING_DRIVER_INTEL_PSTATE "was detected" + " which does not offer userspace power governor" + ". \"intel_pstate=disable\" needs to be added " + "to the kernel boot parameters.\n"); + } + + return -1; + } + + return 0; +} + /** * It is to check the current scaling governor by reading sys file, and then * set it into 'userspace' if it is not by writing the sys file. The original @@ -154,6 +223,11 @@ power_set_governor(unsigned int lcore_id, const char *new_gov, char *old_gov, char buf[BUFSIZ]; char fullpath[PATH_MAX]; + /* check if userspace governor is available */ + if (power_check_gov_userspace(lcore_id)) + return ret; + + /* store current governor and set userspace governor */ snprintf(fullpath, sizeof(fullpath), POWER_SYSFILE_GOVERNOR, lcore_id); fd = open(fullpath, O_RDWR); -- 2.7.4 ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [dpdk-dev] [PATCH 0/3] power: fixes for power ACPI through sysfs 2017-11-11 18:55 ` [dpdk-dev] [PATCH 0/3] power: fixes for power ACPI through sysfs Radoslaw Biernacki ` (2 preceding siblings ...) 2017-11-11 18:55 ` [dpdk-dev] [PATCH 3/3] power: check if userspace governor is available Radoslaw Biernacki @ 2017-11-21 11:09 ` Radoslaw Biernacki 3 siblings, 0 replies; 15+ messages in thread From: Radoslaw Biernacki @ 2017-11-21 11:09 UTC (permalink / raw) To: Hunt, David; +Cc: stable, alan.carew, pablo.de.lara.guarch, dev Hi David, I forgot to add V2 to the topic (sorry for that). But did you had time to look at V2 of this patch? On 11 November 2017 at 19:55, Radoslaw Biernacki < radoslaw.biernacki@linaro.org> wrote: > This series of patches is fixing bug in power ACPI subsystem code as > well as improve the debugging messages and cleans the code. > > V2: > - error checking macros removed (checkpatch warning) > - using plain open()/read()/write() system functions instead of STDIO > - added check for intel_pstate driver together with suggestion about > needed kernel boot parameter > > Radoslaw Biernacki (3): > power: removing code macros > power: switching to unbuffered access for /sys files > power: check if userspace governor is available > > lib/librte_power/rte_power_acpi_cpufreq.c | 304 > ++++++++++++++++++------------ > 1 file changed, 182 insertions(+), 122 deletions(-) > > -- > 2.7.4 > > ^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2018-01-31 23:39 UTC | newest] Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2017-10-16 13:47 [dpdk-dev] [PATCH 1/2] power: switching to unbuffered stdio for /sys file access Radoslaw Biernacki 2017-10-16 13:47 ` [dpdk-dev] [PATCH 2/2] power: check if userspace governor is available Radoslaw Biernacki 2017-10-18 10:53 ` Hunt, David 2017-10-18 14:02 ` Radoslaw Biernacki 2017-10-18 10:28 ` [dpdk-dev] [PATCH 1/2] power: switching to unbuffered stdio for /sys file access Hunt, David 2017-10-18 10:33 ` Hunt, David 2017-10-18 13:56 ` Radoslaw Biernacki 2017-11-11 18:55 ` [dpdk-dev] [PATCH 0/3] power: fixes for power ACPI through sysfs Radoslaw Biernacki 2017-11-11 18:55 ` [dpdk-dev] [PATCH 1/3] power: removing code macros Radoslaw Biernacki 2017-11-11 18:55 ` [dpdk-dev] [PATCH 2/3] power: switching to unbuffered access for /sys files Radoslaw Biernacki 2017-11-23 14:42 ` Hunt, David 2017-12-01 21:01 ` Radoslaw Biernacki 2018-01-31 23:38 ` [dpdk-dev] [dpdk-stable] " Thomas Monjalon 2017-11-11 18:55 ` [dpdk-dev] [PATCH 3/3] power: check if userspace governor is available Radoslaw Biernacki 2017-11-21 11:09 ` [dpdk-dev] [PATCH 0/3] power: fixes for power ACPI through sysfs Radoslaw Biernacki
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).