Merge branches 'pm-opp' and 'pm-tools'

Merge OPP (operating performance points) and tooling updates for
6.11-rc1:

 - Fix missing cleanup on error in _opp_attach_genpd() (Viresh Kumar).

 - Introduce an OF helper function to inform if required-opps is used
   and drop a redundant in-parameter to _set_opp_level() (Ulf Hansson).

 - Update pm-graph to v5.12 which includes fixes and major code revamp
   for python3.12 (Todd Brandt).

 - Address several assorted issues in the cpupower utility (Roman
   Storozhenko).

* pm-opp:
  OPP: Introduce an OF helper function to inform if required-opps is used
  OPP: Drop a redundant in-parameter to _set_opp_level()
  OPP: Fix missing cleanup on error in _opp_attach_genpd()

* pm-tools:
  cpupower: fix lib default installation path
  cpupower: Disable direct build of the 'bench' subproject
  cpupower: Change the var type of the 'monitor' subcommand display mode
  cpupower: Remove absent 'v' parameter from monitor man page
  cpupower: Improve cpupower build process description
  cpupower: Add 'help' target to the main Makefile
  cpupower: Replace a dead reference link with working ones
  pm-graph: v5.12, code revamp for python3.12
  pm-graph: v5.12, fixes
This commit is contained in:
Rafael J. Wysocki 2024-07-15 18:55:14 +02:00
commit a02bed4183
10 changed files with 814 additions and 578 deletions

View file

@ -1102,8 +1102,7 @@ static int _set_required_opps(struct device *dev, struct opp_table *opp_table,
return 0;
}
static int _set_opp_level(struct device *dev, struct opp_table *opp_table,
struct dev_pm_opp *opp)
static int _set_opp_level(struct device *dev, struct dev_pm_opp *opp)
{
unsigned int level = 0;
int ret = 0;
@ -1171,7 +1170,7 @@ static int _disable_opp_table(struct device *dev, struct opp_table *opp_table)
if (opp_table->regulators)
regulator_disable(opp_table->regulators[0]);
ret = _set_opp_level(dev, opp_table, NULL);
ret = _set_opp_level(dev, NULL);
if (ret)
goto out;
@ -1220,7 +1219,7 @@ static int _set_opp(struct device *dev, struct opp_table *opp_table,
return ret;
}
ret = _set_opp_level(dev, opp_table, opp);
ret = _set_opp_level(dev, opp);
if (ret)
return ret;
@ -1267,7 +1266,7 @@ static int _set_opp(struct device *dev, struct opp_table *opp_table,
return ret;
}
ret = _set_opp_level(dev, opp_table, opp);
ret = _set_opp_level(dev, opp);
if (ret)
return ret;
@ -2443,8 +2442,10 @@ static int _opp_attach_genpd(struct opp_table *opp_table, struct device *dev,
* Cross check it again and fix if required.
*/
gdev = dev_to_genpd_dev(virt_dev);
if (IS_ERR(gdev))
return PTR_ERR(gdev);
if (IS_ERR(gdev)) {
ret = PTR_ERR(gdev);
goto err;
}
genpd_table = _find_opp_table(gdev);
if (!IS_ERR(genpd_table)) {

View file

@ -1443,6 +1443,38 @@ int of_get_required_opp_performance_state(struct device_node *np, int index)
}
EXPORT_SYMBOL_GPL(of_get_required_opp_performance_state);
/**
* dev_pm_opp_of_has_required_opp - Find out if a required-opps exists.
* @dev: The device to investigate.
*
* Returns true if the device's node has a "operating-points-v2" property and if
* the corresponding node for the opp-table describes opp nodes that uses the
* "required-opps" property.
*
* Return: True if a required-opps is present, else false.
*/
bool dev_pm_opp_of_has_required_opp(struct device *dev)
{
struct device_node *opp_np, *np;
int count;
opp_np = _opp_of_get_opp_desc_node(dev->of_node, 0);
if (!opp_np)
return false;
np = of_get_next_available_child(opp_np, NULL);
of_node_put(opp_np);
if (!np) {
dev_warn(dev, "Empty OPP table\n");
return false;
}
count = of_count_phandle_with_args(np, "required-opps", NULL);
of_node_put(np);
return count > 0;
}
/**
* dev_pm_opp_get_of_node() - Gets the DT node corresponding to an opp
* @opp: opp for which DT node has to be returned for

View file

@ -474,6 +474,7 @@ int dev_pm_opp_of_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpuma
struct device_node *dev_pm_opp_of_get_opp_desc_node(struct device *dev);
struct device_node *dev_pm_opp_get_of_node(struct dev_pm_opp *opp);
int of_get_required_opp_performance_state(struct device_node *np, int index);
bool dev_pm_opp_of_has_required_opp(struct device *dev);
int dev_pm_opp_of_find_icc_paths(struct device *dev, struct opp_table *opp_table);
int dev_pm_opp_of_register_em(struct device *dev, struct cpumask *cpus);
int dev_pm_opp_calc_power(struct device *dev, unsigned long *uW,
@ -552,6 +553,11 @@ static inline int of_get_required_opp_performance_state(struct device_node *np,
return -EOPNOTSUPP;
}
static inline bool dev_pm_opp_of_has_required_opp(struct device *dev)
{
return false;
}
static inline int dev_pm_opp_of_find_icc_paths(struct device *dev, struct opp_table *opp_table)
{
return -EOPNOTSUPP;

View file

@ -67,6 +67,7 @@ LANGUAGES = de fr it cs pt ka
bindir ?= /usr/bin
sbindir ?= /usr/sbin
mandir ?= /usr/man
libdir ?= /usr/lib
includedir ?= /usr/include
localedir ?= /usr/share/locale
docdir ?= /usr/share/doc/packages/cpupower
@ -94,15 +95,6 @@ RANLIB = $(CROSS)ranlib
HOSTCC = gcc
MKDIR = mkdir
# 64bit library detection
include ../../scripts/Makefile.arch
ifeq ($(IS_64_BIT), 1)
libdir ?= /usr/lib64
else
libdir ?= /usr/lib
endif
# Now we set up the build system
#
@ -332,4 +324,39 @@ uninstall:
rm -f $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupower.mo; \
done;
.PHONY: all utils libcpupower update-po create-gmo install-lib install-tools install-man install-gmo install uninstall clean
help:
@echo 'Building targets:'
@echo ' all - Default target. Could be omitted. Put build artifacts'
@echo ' to "O" cmdline option dir (default: current dir)'
@echo ' install - Install previously built project files from the output'
@echo ' dir defined by "O" cmdline option (default: current dir)'
@echo ' to the install dir defined by "DESTDIR" cmdline or'
@echo ' Makefile config block option (default: "")'
@echo ' install-lib - Install previously built library binary from the output'
@echo ' dir defined by "O" cmdline option (default: current dir)'
@echo ' and library headers from "lib/" for userspace to the install'
@echo ' dir defined by "DESTDIR" cmdline (default: "")'
@echo ' install-tools - Install previously built "cpupower" util from the output'
@echo ' dir defined by "O" cmdline option (default: current dir) and'
@echo ' "cpupower-completion.sh" script from the src dir to the'
@echo ' install dir defined by "DESTDIR" cmdline or Makefile'
@echo ' config block option (default: "")'
@echo ' install-man - Install man pages from the "man" src subdir to the'
@echo ' install dir defined by "DESTDIR" cmdline or Makefile'
@echo ' config block option (default: "")'
@echo ' install-gmo - Install previously built language files from the output'
@echo ' dir defined by "O" cmdline option (default: current dir)'
@echo ' to the install dir defined by "DESTDIR" cmdline or Makefile'
@echo ' config block option (default: "")'
@echo ' install-bench - Install previously built "cpufreq-bench" util files from the'
@echo ' output dir defined by "O" cmdline option (default: current dir)'
@echo ' to the install dir defined by "DESTDIR" cmdline or Makefile'
@echo ' config block option (default: "")'
@echo ''
@echo 'Cleaning targets:'
@echo ' clean - Clean build artifacts from the dir defined by "O" cmdline'
@echo ' option (default: current dir)'
@echo ' uninstall - Remove previously installed files from the dir defined by "DESTDIR"'
@echo ' cmdline or Makefile config block option (default: "")'
.PHONY: all utils libcpupower update-po create-gmo install-lib install-tools install-man install-gmo install uninstall clean help

View file

@ -22,16 +22,156 @@ interfaces [depending on configuration, see below].
compilation and installation
----------------------------
make
su
make install
There are 2 output directories - one for the build output and another for
the installation of the build results, that is the utility, library,
man pages, etc...
should suffice on most systems. It builds libcpupower to put in
/usr/lib; cpupower, cpufreq-bench_plot.sh to put in /usr/bin; and
cpufreq-bench to put in /usr/sbin. If you want to set up the paths
differently and/or want to configure the package to your specific
needs, you need to open "Makefile" with an editor of your choice and
edit the block marked CONFIGURATION.
default directory
-----------------
In the case of default directory, build and install process requires no
additional parameters:
build
-----
$ make
The output directory for the 'make' command is the current directory and
its subdirs in the kernel tree:
tools/power/cpupower
install
-------
$ sudo make install
'make install' command puts targets to default system dirs:
-----------------------------------------------------------------------
| Installing file | System dir |
-----------------------------------------------------------------------
| libcpupower | /usr/lib |
-----------------------------------------------------------------------
| cpupower | /usr/bin |
-----------------------------------------------------------------------
| cpufreq-bench_plot.sh | /usr/bin |
-----------------------------------------------------------------------
| man pages | /usr/man |
-----------------------------------------------------------------------
To put it in other words it makes build results available system-wide,
enabling any user to simply start using it without any additional steps
custom directory
----------------
There are 2 make's command-line variables 'O' and 'DESTDIR' that setup
appropriate dirs:
'O' - build directory
'DESTDIR' - installation directory. This variable could also be setup in
the 'CONFIGURATION' block of the "Makefile"
build
-----
$ make O=<your_custom_build_catalog>
Example:
$ make O=/home/hedin/prj/cpupower/build
install
-------
$ make O=<your_custom_build_catalog> DESTDIR=<your_custom_install_catalog>
Example:
$ make O=/home/hedin/prj/cpupower/build DESTDIR=/home/hedin/prj/cpupower \
> install
Notice that both variables 'O' and 'DESTDIR' have been provided. The reason
is that the build results are saved in the custom output dir defined by 'O'
variable. So, this dir is the source for the installation step. If only
'DESTDIR' were provided then the 'install' target would assume that the
build directory is the current one, build everything there and install
from the current dir.
The files will be installed to the following dirs:
-----------------------------------------------------------------------
| Installing file | System dir |
-----------------------------------------------------------------------
| libcpupower | ${DESTDIR}/usr/lib |
-----------------------------------------------------------------------
| cpupower | ${DESTDIR}/usr/bin |
-----------------------------------------------------------------------
| cpufreq-bench_plot.sh | ${DESTDIR}/usr/bin |
-----------------------------------------------------------------------
| man pages | ${DESTDIR}/usr/man |
-----------------------------------------------------------------------
If you look at the table for the default 'make' output dirs you will
notice that the only difference with the non-default case is the
${DESTDIR} prefix. So, the structure of the output dirs remains the same
regardles of the root output directory.
clean and uninstall
-------------------
'clean' target is intended for cleanup the build catalog from build results
'uninstall' target is intended for removing installed files from the
installation directory
default directory
-----------------
This case is a straightforward one:
$ make clean
$ make uninstall
custom directory
----------------
Use 'O' command line variable to remove previously built files from the
build dir:
$ make O=<your_custom_build_catalog> clean
Example:
$ make O=/home/hedin/prj/cpupower/build clean
Use 'DESTDIR' command line variable to uninstall previously installed files
from the given dir:
$ make DESTDIR=<your_custom_install_catalog>
Example:
make DESTDIR=/home/hedin/prj/cpupower uninstall
running the tool
----------------
default directory
-----------------
$ sudo cpupower
custom directory
----------------
When it comes to run the utility from the custom build catalog things
become a little bit complicated as 'just run' approach doesn't work.
Assuming that the current dir is '<your_custom_install_catalog>/usr',
issuing the following command:
$ sudo ./bin/cpupower
will produce the following error output:
./bin/cpupower: error while loading shared libraries: libcpupower.so.1:
cannot open shared object file: No such file or directory
The issue is that binary cannot find the 'libcpupower' library. So, we
shall point to the lib dir:
sudo LD_LIBRARY_PATH=lib64/ ./bin/cpupower
THANKS

View file

@ -1,4 +1,9 @@
# SPDX-License-Identifier: GPL-2.0
ifeq ($(MAKELEVEL),0)
$(error This Makefile is not intended to be run standalone, but only as a part \
of the main one in the parent dir)
endif
OUTPUT := ./
ifeq ("$(origin O)", "command line")
ifneq ($(O),)

View file

@ -81,11 +81,6 @@ Measure idle and frequency characteristics of an arbitrary command/workload.
The executable \fBcommand\fP is forked and upon its exit, statistics gathered since it was
forked are displayed.
.RE
.PP
\-v
.RS 4
Increase verbosity if the binary was compiled with the DEBUG option set.
.RE
.SH MONITOR DESCRIPTIONS
.SS "Idle_Stats"
@ -172,9 +167,11 @@ displayed.
"BIOS and Kernel Developers Guide (BKDG) for AMD Family 14h Processors"
https://support.amd.com/us/Processor_TechDocs/43170.pdf
"Intel® Turbo Boost Technology
in Intel® Core™ Microarchitecture (Nehalem) Based Processors"
http://download.intel.com/design/processor/applnots/320354.pdf
"What Is Intel® Turbo Boost Technology?"
https://www.intel.com/content/www/us/en/gaming/resources/turbo-boost.html
"Power Management - Technology Overview"
https://cdrdv2.intel.com/v1/dl/getContent/637748
"Intel® 64 and IA-32 Architectures Software Developer's Manual
Volume 3B: System Programming Guide"

View file

@ -35,7 +35,7 @@ static unsigned int avail_monitors;
static char *progname;
enum operation_mode_e { list = 1, show, show_all };
static int mode;
static enum operation_mode_e mode;
static int interval = 1;
static char *show_monitors_param;
static struct cpupower_topology cpu_top;

View file

@ -77,12 +77,12 @@ class SystemValues(aslib.SystemValues):
fp.close()
self.testdir = datetime.now().strftime('boot-%y%m%d-%H%M%S')
def kernelVersion(self, msg):
m = re.match('^[Ll]inux *[Vv]ersion *(?P<v>\S*) .*', msg)
m = re.match(r'^[Ll]inux *[Vv]ersion *(?P<v>\S*) .*', msg)
if m:
return m.group('v')
return 'unknown'
def checkFtraceKernelVersion(self):
m = re.match('^(?P<x>[0-9]*)\.(?P<y>[0-9]*)\.(?P<z>[0-9]*).*', self.kernel)
m = re.match(r'^(?P<x>[0-9]*)\.(?P<y>[0-9]*)\.(?P<z>[0-9]*).*', self.kernel)
if m:
val = tuple(map(int, m.groups()))
if val >= (4, 10, 0):
@ -324,7 +324,7 @@ def parseKernelLog():
idx = line.find('[')
if idx > 1:
line = line[idx:]
m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line)
m = re.match(r'[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line)
if(not m):
continue
ktime = float(m.group('ktime'))
@ -332,24 +332,24 @@ def parseKernelLog():
break
msg = m.group('msg')
data.dmesgtext.append(line)
if(ktime == 0.0 and re.match('^Linux version .*', msg)):
if(ktime == 0.0 and re.match(r'^Linux version .*', msg)):
if(not sysvals.stamp['kernel']):
sysvals.stamp['kernel'] = sysvals.kernelVersion(msg)
continue
m = re.match('.* setting system clock to (?P<d>[0-9\-]*)[ A-Z](?P<t>[0-9:]*) UTC.*', msg)
m = re.match(r'.* setting system clock to (?P<d>[0-9\-]*)[ A-Z](?P<t>[0-9:]*) UTC.*', msg)
if(m):
bt = datetime.strptime(m.group('d')+' '+m.group('t'), '%Y-%m-%d %H:%M:%S')
bt = bt - timedelta(seconds=int(ktime))
data.boottime = bt.strftime('%Y-%m-%d_%H:%M:%S')
sysvals.stamp['time'] = bt.strftime('%B %d %Y, %I:%M:%S %p')
continue
m = re.match('^calling *(?P<f>.*)\+.* @ (?P<p>[0-9]*)', msg)
m = re.match(r'^calling *(?P<f>.*)\+.* @ (?P<p>[0-9]*)', msg)
if(m):
func = m.group('f')
pid = int(m.group('p'))
devtemp[func] = (ktime, pid)
continue
m = re.match('^initcall *(?P<f>.*)\+.* returned (?P<r>.*) after (?P<t>.*) usecs', msg)
m = re.match(r'^initcall *(?P<f>.*)\+.* returned (?P<r>.*) after (?P<t>.*) usecs', msg)
if(m):
data.valid = True
data.end = ktime
@ -359,7 +359,7 @@ def parseKernelLog():
data.newAction(phase, f, pid, start, ktime, int(r), int(t))
del devtemp[f]
continue
if(re.match('^Freeing unused kernel .*', msg)):
if(re.match(r'^Freeing unused kernel .*', msg)):
data.tUserMode = ktime
data.dmesg['kernel']['end'] = ktime
data.dmesg['user']['start'] = ktime

File diff suppressed because it is too large Load diff