* [GIT PULL] Power management updates for v5.3-rc1
From: Rafael J. Wysocki @ 2019-07-08 21:36 UTC (permalink / raw)
To: Linus Torvalds
Cc: Linux PM, ACPI Devel Maling List, Linux PCI,
Linux Kernel Mailing List
Hi Linus,
Please pull from the tag
git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git \
pm-5.3-rc1
with top-most commit 586a07dca8c51b966960d1f0d8be9c27d7e0a95c
Merge branch 'pm-cpufreq'
on top of commit 6fbc7275c7a9ba97877050335f290341a1fd8dbf
Linux 5.2-rc7
to receive power management updates for 5.3-rc1.
These update PCI and ACPI power management (improved handling of
ACPI power resources and PCIe link delays, fixes related to corner
cases, hibernation handling rework), fix and extend the operating
performance points (OPP) framework, add new cpufreq drivers for
Raspberry Pi and imx8m chips, update some other cpufreq drivers,
clean up assorted pieces of PM code and documentation and update
tools.
Specifics:
- Improve the handling of shared ACPI power resources in the PCI
bus type layer (Mika Westerberg).
- Make the PCI layer take link delays required by the PCIe spec
into account as appropriate and avoid polling devices in D3cold
for PME (Mika Westerberg).
- Fix some corner case issues in ACPI device power management and
in the PCI bus type layer, optimiza and clean up the handling of
runtime-suspended PCI devices during system-wide transitions to
sleep states (Rafael Wysocki).
- Rework hibernation handling in the ACPI core and the PCI bus type
to resume runtime-suspended devices before hibernation (which
allows some functional problems to be avoided) and fix some ACPI
power management issues related to hiberation (Rafael Wysocki).
- Extend the operating performance points (OPP) framework to support
a wider range of devices (Rajendra Nayak, Stehpen Boyd).
- Fix issues related to genpd_virt_devs and issues with platforms
using the set_opp() callback in the OPP framework (Viresh Kumar,
Dmitry Osipenko).
- Add new cpufreq driver for Raspberry Pi (Nicolas Saenz Julienne).
- Add new cpufreq driver for imx8m and imx7d chips (Leonard Crestez).
- Fix and clean up the pcc-cpufreq, brcmstb-avs-cpufreq, s5pv210,
and armada-37xx cpufreq drivers (David Arcari, Florian Fainelli,
Paweł Chmiel, YueHaibing).
- Clean up and fix the cpufreq core (Viresh Kumar, Daniel Lezcano).
- Fix minor issue in the ACPI system sleep support code and export
one function from it (Lenny Szubowicz, Dexuan Cui).
- Clean up assorted pieces of PM code and documentation (Kefeng Wang,
Andy Shevchenko, Bart Van Assche, Greg Kroah-Hartman, Fuqian Huang,
Geert Uytterhoeven, Mathieu Malaterre, Rafael Wysocki).
- Update the pm-graph utility to v5.4 (Todd Brandt).
- Fix and clean up the cpupower utility (Abhishek Goel, Nick Black).
Thanks!
---------------
Abhishek Goel (1):
cpupower : frequency-set -r option misses the last cpu in related cpu list
Andy Shevchenko (1):
ACPI / sleep: Switch to use acpi_dev_get_first_match_dev()
Bart Van Assche (1):
PM: sleep: Show how long dpm_suspend_start() and dpm_suspend_end() take
Daniel Lezcano (1):
cpufreq: Move the IS_ENABLED(CPU_THERMAL) macro into a stub
David Arcari (1):
cpufreq: pcc-cpufreq: Fail initialization if driver cannot be registered
Dexuan Cui (1):
ACPI: PM: Make acpi_sleep_state_supported() non-static
Dmitry Osipenko (1):
opp: Don't use IS_ERR on invalid supplies
Florian Fainelli (2):
cpufreq: brcmstb-avs-cpufreq: Fix initial command check
cpufreq: brcmstb-avs-cpufreq: Fix types for voltage/frequency
Fuqian Huang (1):
kernel: power: swap: use kzalloc() instead of kmalloc() followed
by memset()
Geert Uytterhoeven (2):
PM / clk: Remove error message on out-of-memory condition
Documentation: ABI: power: Add missing newline at end of file
Greg Kroah-Hartman (2):
power: avs: smartreflex: no need to check return value of
debugfs_create functions
drivers: base: power: remove wakeup_sources_stats_dentry variable
Kefeng Wang (1):
drivers: base: power: clock_ops: Use of_clk_get_parent_count()
Lenny Szubowicz (1):
ACPI / LPIT: Correct LPIT end address for lpit_process()
Leonard Crestez (5):
cpufreq: Add imx-cpufreq-dt driver
dt-bindings: imx-cpufreq-dt: Document opp-supported-hw usage
cpufreq: imx-cpufreq-dt: Fix no OPPs available on unfused parts
cpufreq: imx-cpufreq-dt: Remove global platform match list
cpufreq: Switch imx7d to imx-cpufreq-dt for speed grading
Mathieu Malaterre (1):
PM: hibernate: powerpc: Expose pfn_is_nosave() prototype
Mika Westerberg (5):
PCI: Add missing link delays required by the PCIe spec
PCI: Do not poll for PME if the device is in D3cold
PCI / ACPI: Use cached ACPI device state to get PCI device power state
ACPI / PM: Introduce concept of a _PR0 dependent device
PCI / ACPI: Add _PR0 dependent devices
Nick Black (1):
cpupower: correct spelling of interval
Nicolas Saenz Julienne (1):
cpufreq: add driver for Raspberry Pi
Paweł Chmiel (1):
cpufreq: s5pv210: Don't flood kernel log after cpufreq change
Rafael J. Wysocki (14):
PCI: PM: Avoid resuming devices in D3hot during system suspend
PCI: PM: Replace pci_dev_keep_suspended() with two functions
PM: suspend: Rename pm_suspend_via_s2idle()
PM: sleep: Update struct wakeup_source documentation
ACPI: PM: Avoid evaluating _PS3 on transitions from D3hot to D3cold
ACPI: PM: Allow transitions to D0 to occur in special cases
PCI: PM/ACPI: Refresh all stale power state data in pci_pm_complete()
PM: ACPI/PCI: Resume all devices during hibernation
PCI: PM: Simplify bus-level hibernation callbacks
ACPI: PM: Simplify and fix PM domain hibernation callbacks
ACPI: PM: Introduce "poweroff" callbacks for ACPI PM domain and LPSS
ACPI: PM: Drop unused function and function header
ACPI: PM: Unexport acpi_device_get_power()
PM: sleep: Drop dev_pm_skip_next_resume_phases()
Rajendra Nayak (1):
opp: Make dev_pm_opp_set_rate() handle freq = 0 to drop performance votes
Stephen Boyd (1):
opp: Don't overwrite rounded clk rate
Todd Brandt (3):
Update to pm-graph 5.3
Update to pm-graph 5.4
Add README and update pm-graph and sleepgraph docs
Viresh Kumar (7):
opp: Attach genpds to devices from within OPP core
opp: Allocate genpd_virt_devs from dev_pm_opp_attach_genpd()
cpufreq: Remove redundant !setpolicy check
cpufreq: Use has_target() instead of !setpolicy
cpufreq: Don't skip frequency validation for has_target() drivers
cpufreq: Consolidate cpufreq_update_current_freq() and __cpufreq_get()
cpufreq: Avoid calling cpufreq_verify_current_freq() from handle_update()
YueHaibing (1):
cpufreq: armada-37xx: Remove set but not used variable 'freq'
---------------
Documentation/ABI/testing/sysfs-power | 2 +-
.../devicetree/bindings/cpufreq/imx-cpufreq-dt.txt | 37 +
arch/powerpc/kernel/suspend.c | 1 +
arch/s390/kernel/entry.h | 1 -
drivers/acpi/acpi_lpit.c | 7 +-
drivers/acpi/acpi_lpss.c | 111 ++-
drivers/acpi/device_pm.c | 165 ++--
drivers/acpi/internal.h | 7 +
drivers/acpi/power.c | 135 ++++
drivers/acpi/sleep.c | 22 +-
drivers/base/power/clock_ops.c | 6 +-
drivers/base/power/main.c | 36 +-
drivers/base/power/wakeup.c | 6 +-
drivers/cpufreq/Kconfig.arm | 17 +
drivers/cpufreq/Makefile | 2 +
drivers/cpufreq/armada-37xx-cpufreq.c | 4 +-
drivers/cpufreq/brcmstb-avs-cpufreq.c | 12 +-
drivers/cpufreq/cpufreq-dt-platdev.c | 5 +-
drivers/cpufreq/cpufreq.c | 121 ++-
drivers/cpufreq/imx-cpufreq-dt.c | 97 +++
drivers/cpufreq/pcc-cpufreq.c | 4 +-
drivers/cpufreq/raspberrypi-cpufreq.c | 97 +++
drivers/cpufreq/s5pv210-cpufreq.c | 2 +-
drivers/input/serio/i8042.c | 2 +-
drivers/opp/core.c | 174 +++--
drivers/opp/of.c | 30 +-
drivers/pci/pci-acpi.c | 14 +-
drivers/pci/pci-driver.c | 74 +-
drivers/pci/pci.c | 116 ++-
drivers/pci/pci.h | 8 +-
drivers/pci/pcie/portdrv_core.c | 66 ++
drivers/power/avs/smartreflex.c | 41 +-
drivers/soc/imx/soc-imx8.c | 3 +
include/acpi/acpi_bus.h | 11 +-
include/linux/acpi.h | 14 +-
include/linux/cpufreq.h | 6 +
include/linux/pm.h | 1 -
include/linux/pm_opp.h | 8 +-
include/linux/pm_wakeup.h | 2 +-
include/linux/suspend.h | 5 +-
kernel/power/power.h | 2 -
kernel/power/suspend.c | 6 +-
kernel/power/swap.c | 3 +-
tools/power/cpupower/man/cpupower-monitor.1 | 2 +-
tools/power/cpupower/po/cs.po | 2 +-
tools/power/cpupower/po/de.po | 2 +-
tools/power/cpupower/po/fr.po | 2 +-
tools/power/cpupower/po/it.po | 2 +-
tools/power/cpupower/po/pt.po | 2 +-
tools/power/cpupower/utils/cpufreq-set.c | 2 +
tools/power/pm-graph/README | 552 +++++++++++++
tools/power/pm-graph/bootgraph.py | 8 +-
tools/power/pm-graph/config/example.cfg | 26 +
tools/power/pm-graph/sleepgraph.8 | 16 +-
tools/power/pm-graph/sleepgraph.py | 857 ++++++++++++++++-----
55 files changed, 2325 insertions(+), 631 deletions(-)
^ permalink raw reply
* Re: [PATCH] tools/power/x86/intel-speed-select: Add .gitignore file
From: Andy Shevchenko @ 2019-07-08 19:48 UTC (permalink / raw)
To: Prarit Bhargava; +Cc: Linux PM, Srinivas Pandruvada, David Arcari
In-Reply-To: <20190708173156.30902-1-prarit@redhat.com>
On Mon, Jul 8, 2019 at 8:32 PM Prarit Bhargava <prarit@redhat.com> wrote:
>
> Andy, could you please add this patch to Srinivas' intel-speed-select
> patchset?
Please, sent it as usual and I will add it.
The series can't be modified anymore (it's published).
>
> Thanks,
>
> P.
> ---8<---
>
> Add a .gitignore file for build include/ and final binary.
>
> Signed-off-by: Prarit Bhargava <prarit@redhat.com>
> Cc: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
> Cc: Andy Shevchenko <andy.shevchenko@gmail.com>
> Cc: David Arcari <darcari@redhat.com>
> ---
> tools/power/x86/intel-speed-select/.gitignore | 2 ++
> 1 file changed, 2 insertions(+)
> create mode 100644 tools/power/x86/intel-speed-select/.gitignore
>
> diff --git a/tools/power/x86/intel-speed-select/.gitignore b/tools/power/x86/intel-speed-select/.gitignore
> new file mode 100644
> index 000000000000..f61145925ce9
> --- /dev/null
> +++ b/tools/power/x86/intel-speed-select/.gitignore
> @@ -0,0 +1,2 @@
> +include/
> +intel-speed-select
> --
> 2.21.0
>
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH v4 1/5] dt-bindings: interconnect: Add Qualcomm QCS404 DT bindings
From: Bjorn Andersson @ 2019-07-08 19:26 UTC (permalink / raw)
To: Georgi Djakov
Cc: robh+dt, agross, vkoul, evgreen, daidavid1, linux-pm, devicetree,
linux-kernel, linux-arm-msm
In-Reply-To: <20190613151323.10850-2-georgi.djakov@linaro.org>
On Thu 13 Jun 08:13 PDT 2019, Georgi Djakov wrote:
> The Qualcomm QCS404 platform has several buses that could be controlled
> and tuned according to the bandwidth demand.
>
> Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org>
> ---
>
> v4:
> - Add the DT header into this patch.
> - Pick Bjorn's r-b.
>
> v3:
> - Add a reg property and move the interconnect nodes under the "soc" node.
>
> v2:
> - No changes.
>
> .../bindings/interconnect/qcom,qcs404.txt | 46 ++++++++++
> .../dt-bindings/interconnect/qcom,qcs404.h | 88 +++++++++++++++++++
> 2 files changed, 134 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/interconnect/qcom,qcs404.txt
> create mode 100644 include/dt-bindings/interconnect/qcom,qcs404.h
>
> diff --git a/Documentation/devicetree/bindings/interconnect/qcom,qcs404.txt b/Documentation/devicetree/bindings/interconnect/qcom,qcs404.txt
> new file mode 100644
> index 000000000000..14a827268dda
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/interconnect/qcom,qcs404.txt
> @@ -0,0 +1,46 @@
> +Qualcomm QCS404 Network-On-Chip interconnect driver binding
> +-----------------------------------------------------------
> +
> +Required properties :
> +- compatible : shall contain only one of the following:
> + "qcom,qcs404-bimc"
> + "qcom,qcs404-pcnoc"
> + "qcom,qcs404-snoc"
> +- #interconnect-cells : should contain 1
> +
> +Optional properties :
> +reg : specifies the physical base address and size of registers
> +clocks : list of phandles and specifiers to all interconnect bus clocks
> +clock-names : clock names should include both "bus_clk" and "bus_a_clk"
Spoke to Rob about this patch, and I don't think these properties should
not be described as optional.
The reg isn't used unless we're implementing support for QoS, but let's
include them in the binding as required anyways.
Iirc the two clocks are required with the current implementation, but
shouldn't there be an iface clock as well, for accessing the QoS
register space?
PS. As I read this again, please drop _clk from the two clocks names -
we know they are clocks...
Regards,
Bjorn
> +
> +Example:
> +
> +soc {
> + ...
> + bimc: interconnect@400000 {
> + reg = <0x00400000 0x80000>;
> + compatible = "qcom,qcs404-bimc";
> + #interconnect-cells = <1>;
> + clock-names = "bus_clk", "bus_a_clk";
> + clocks = <&rpmcc RPM_SMD_BIMC_CLK>,
> + <&rpmcc RPM_SMD_BIMC_A_CLK>;
> + };
> +
> + pnoc: interconnect@500000 {
> + reg = <0x00500000 0x15080>;
> + compatible = "qcom,qcs404-pcnoc";
> + #interconnect-cells = <1>;
> + clock-names = "bus_clk", "bus_a_clk";
> + clocks = <&rpmcc RPM_SMD_PNOC_CLK>,
> + <&rpmcc RPM_SMD_PNOC_A_CLK>;
> + };
> +
> + snoc: interconnect@580000 {
> + reg = <0x00580000 0x23080>;
> + compatible = "qcom,qcs404-snoc";
> + #interconnect-cells = <1>;
> + clock-names = "bus_clk", "bus_a_clk";
> + clocks = <&rpmcc RPM_SMD_SNOC_CLK>,
> + <&rpmcc RPM_SMD_SNOC_A_CLK>;
> + };
> +};
> diff --git a/include/dt-bindings/interconnect/qcom,qcs404.h b/include/dt-bindings/interconnect/qcom,qcs404.h
> new file mode 100644
> index 000000000000..960f6e39c5f2
> --- /dev/null
> +++ b/include/dt-bindings/interconnect/qcom,qcs404.h
> @@ -0,0 +1,88 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Qualcomm interconnect IDs
> + *
> + * Copyright (c) 2019, Linaro Ltd.
> + * Author: Georgi Djakov <georgi.djakov@linaro.org>
> + */
> +
> +#ifndef __DT_BINDINGS_INTERCONNECT_QCOM_QCS404_H
> +#define __DT_BINDINGS_INTERCONNECT_QCOM_QCS404_H
> +
> +#define MASTER_AMPSS_M0 0
> +#define MASTER_OXILI 1
> +#define MASTER_MDP_PORT0 2
> +#define MASTER_SNOC_BIMC_1 3
> +#define MASTER_TCU_0 4
> +#define SLAVE_EBI_CH0 5
> +#define SLAVE_BIMC_SNOC 6
> +
> +#define MASTER_SPDM 0
> +#define MASTER_BLSP_1 1
> +#define MASTER_BLSP_2 2
> +#define MASTER_XI_USB_HS1 3
> +#define MASTER_CRYPT0 4
> +#define MASTER_SDCC_1 5
> +#define MASTER_SDCC_2 6
> +#define MASTER_SNOC_PCNOC 7
> +#define MASTER_QPIC 8
> +#define PCNOC_INT_0 9
> +#define PCNOC_INT_2 10
> +#define PCNOC_INT_3 11
> +#define PCNOC_S_0 12
> +#define PCNOC_S_1 13
> +#define PCNOC_S_2 14
> +#define PCNOC_S_3 15
> +#define PCNOC_S_4 16
> +#define PCNOC_S_6 17
> +#define PCNOC_S_7 18
> +#define PCNOC_S_8 19
> +#define PCNOC_S_9 20
> +#define PCNOC_S_10 21
> +#define PCNOC_S_11 22
> +#define SLAVE_SPDM 23
> +#define SLAVE_PDM 24
> +#define SLAVE_PRNG 25
> +#define SLAVE_TCSR 26
> +#define SLAVE_SNOC_CFG 27
> +#define SLAVE_MESSAGE_RAM 28
> +#define SLAVE_DISP_SS_CFG 29
> +#define SLAVE_GPU_CFG 30
> +#define SLAVE_BLSP_1 31
> +#define SLAVE_BLSP_2 32
> +#define SLAVE_TLMM_NORTH 33
> +#define SLAVE_PCIE 34
> +#define SLAVE_ETHERNET 35
> +#define SLAVE_TLMM_EAST 36
> +#define SLAVE_TCU 37
> +#define SLAVE_PMIC_ARB 38
> +#define SLAVE_SDCC_1 39
> +#define SLAVE_SDCC_2 40
> +#define SLAVE_TLMM_SOUTH 41
> +#define SLAVE_USB_HS 42
> +#define SLAVE_USB3 43
> +#define SLAVE_CRYPTO_0_CFG 44
> +#define SLAVE_PCNOC_SNOC 45
> +
> +#define MASTER_QDSS_BAM 0
> +#define MASTER_BIMC_SNOC 1
> +#define MASTER_PCNOC_SNOC 2
> +#define MASTER_QDSS_ETR 3
> +#define MASTER_EMAC 4
> +#define MASTER_PCIE 5
> +#define MASTER_USB3 6
> +#define QDSS_INT 7
> +#define SNOC_INT_0 8
> +#define SNOC_INT_1 9
> +#define SNOC_INT_2 10
> +#define SLAVE_KPSS_AHB 11
> +#define SLAVE_WCSS 12
> +#define SLAVE_SNOC_BIMC_1 13
> +#define SLAVE_IMEM 14
> +#define SLAVE_SNOC_PCNOC 15
> +#define SLAVE_QDSS_STM 16
> +#define SLAVE_CATS_0 17
> +#define SLAVE_CATS_1 18
> +#define SLAVE_LPASS 19
> +
> +#endif
^ permalink raw reply
* [PATCH v8 07/11] x86/acpi: Adapt assembly for PIE support
From: Thomas Garnier @ 2019-07-08 17:49 UTC (permalink / raw)
To: kernel-hardening
Cc: kristen, keescook, Thomas Garnier, Pavel Machek,
Rafael J . Wysocki, Rafael J. Wysocki, Len Brown, Thomas Gleixner,
Ingo Molnar, Borislav Petkov, H. Peter Anvin, x86, linux-pm,
linux-kernel
In-Reply-To: <20190708174913.123308-1-thgarnie@chromium.org>
Change the assembly code to use only relative references of symbols for the
kernel to be PIE compatible.
Position Independent Executable (PIE) support will allow to extend the
KASLR randomization range below 0xffffffff80000000.
Signed-off-by: Thomas Garnier <thgarnie@chromium.org>
Acked-by: Pavel Machek <pavel@ucw.cz>
Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
---
arch/x86/kernel/acpi/wakeup_64.S | 31 ++++++++++++++++---------------
1 file changed, 16 insertions(+), 15 deletions(-)
diff --git a/arch/x86/kernel/acpi/wakeup_64.S b/arch/x86/kernel/acpi/wakeup_64.S
index b0715c3ac18d..3ec6c1b74ad4 100644
--- a/arch/x86/kernel/acpi/wakeup_64.S
+++ b/arch/x86/kernel/acpi/wakeup_64.S
@@ -15,7 +15,7 @@
* Hooray, we are in Long 64-bit mode (but still running in low memory)
*/
ENTRY(wakeup_long64)
- movq saved_magic, %rax
+ movq saved_magic(%rip), %rax
movq $0x123456789abcdef0, %rdx
cmpq %rdx, %rax
jne bogus_64_magic
@@ -26,14 +26,14 @@ ENTRY(wakeup_long64)
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
- movq saved_rsp, %rsp
+ movq saved_rsp(%rip), %rsp
- movq saved_rbx, %rbx
- movq saved_rdi, %rdi
- movq saved_rsi, %rsi
- movq saved_rbp, %rbp
+ movq saved_rbx(%rip), %rbx
+ movq saved_rdi(%rip), %rdi
+ movq saved_rsi(%rip), %rsi
+ movq saved_rbp(%rip), %rbp
- movq saved_rip, %rax
+ movq saved_rip(%rip), %rax
jmp *%rax
ENDPROC(wakeup_long64)
@@ -46,7 +46,7 @@ ENTRY(do_suspend_lowlevel)
xorl %eax, %eax
call save_processor_state
- movq $saved_context, %rax
+ leaq saved_context(%rip), %rax
movq %rsp, pt_regs_sp(%rax)
movq %rbp, pt_regs_bp(%rax)
movq %rsi, pt_regs_si(%rax)
@@ -65,13 +65,14 @@ ENTRY(do_suspend_lowlevel)
pushfq
popq pt_regs_flags(%rax)
- movq $.Lresume_point, saved_rip(%rip)
+ leaq .Lresume_point(%rip), %rax
+ movq %rax, saved_rip(%rip)
- movq %rsp, saved_rsp
- movq %rbp, saved_rbp
- movq %rbx, saved_rbx
- movq %rdi, saved_rdi
- movq %rsi, saved_rsi
+ movq %rsp, saved_rsp(%rip)
+ movq %rbp, saved_rbp(%rip)
+ movq %rbx, saved_rbx(%rip)
+ movq %rdi, saved_rdi(%rip)
+ movq %rsi, saved_rsi(%rip)
addq $8, %rsp
movl $3, %edi
@@ -83,7 +84,7 @@ ENTRY(do_suspend_lowlevel)
.align 4
.Lresume_point:
/* We don't restore %rax, it must be 0 anyway */
- movq $saved_context, %rax
+ leaq saved_context(%rip), %rax
movq saved_context_cr4(%rax), %rbx
movq %rbx, %cr4
movq saved_context_cr3(%rax), %rbx
--
2.22.0.410.gd8fdbe21b5-goog
^ permalink raw reply related
* [PATCH v8 09/11] x86/power/64: Adapt assembly for PIE support
From: Thomas Garnier @ 2019-07-08 17:49 UTC (permalink / raw)
To: kernel-hardening
Cc: kristen, keescook, Thomas Garnier, Pavel Machek,
Rafael J . Wysocki, Rafael J. Wysocki, Thomas Gleixner,
Ingo Molnar, Borislav Petkov, H. Peter Anvin, x86, linux-pm,
linux-kernel
In-Reply-To: <20190708174913.123308-1-thgarnie@chromium.org>
Change the assembly code to use only relative references of symbols for the
kernel to be PIE compatible.
Position Independent Executable (PIE) support will allow to extend the
KASLR randomization range below 0xffffffff80000000.
Signed-off-by: Thomas Garnier <thgarnie@chromium.org>
Acked-by: Pavel Machek <pavel@ucw.cz>
Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
---
arch/x86/power/hibernate_asm_64.S | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/x86/power/hibernate_asm_64.S b/arch/x86/power/hibernate_asm_64.S
index a4d5eb0a7ece..796cd19d575b 100644
--- a/arch/x86/power/hibernate_asm_64.S
+++ b/arch/x86/power/hibernate_asm_64.S
@@ -23,7 +23,7 @@
#include <asm/frame.h>
ENTRY(swsusp_arch_suspend)
- movq $saved_context, %rax
+ leaq saved_context(%rip), %rax
movq %rsp, pt_regs_sp(%rax)
movq %rbp, pt_regs_bp(%rax)
movq %rsi, pt_regs_si(%rax)
@@ -114,7 +114,7 @@ ENTRY(restore_registers)
movq %rax, %cr4; # turn PGE back on
/* We don't restore %rax, it must be 0 anyway */
- movq $saved_context, %rax
+ leaq saved_context(%rip), %rax
movq pt_regs_sp(%rax), %rsp
movq pt_regs_bp(%rax), %rbp
movq pt_regs_si(%rax), %rsi
--
2.22.0.410.gd8fdbe21b5-goog
^ permalink raw reply related
* [PATCH v8 00/11] x86: PIE support to extend KASLR randomization
From: Thomas Garnier @ 2019-07-08 17:48 UTC (permalink / raw)
To: kernel-hardening
Cc: kristen, keescook, Herbert Xu, David S. Miller, Thomas Gleixner,
Ingo Molnar, Borislav Petkov, H. Peter Anvin, x86,
Andy Lutomirski, Juergen Gross, Alok Kataria, Rafael J. Wysocki,
Len Brown, Pavel Machek, Peter Zijlstra, Thomas Garnier,
Nadav Amit, Jann Horn, Andrew Morton, Boris Ostrovsky, Feng Tang,
Maran Wilson, Enrico Weigelt, Greg Kroah-Hartman, Alexios Zavras,
linux-crypto, linux-kernel, virtualization, linux-pm
Splitting the previous serie in two. This part contains assembly code
changes required for PIE but without any direct dependencies with the
rest of the patchset.
Changes:
- patch v8 (assembly):
- Fix issues in crypto changes (thanks to Eric Biggers).
- Remove unnecessary jump table change.
- Change author and signoff to chromium email address.
- patch v7 (assembly):
- Split patchset and reorder changes.
- patch v6:
- Rebase on latest changes in jump tables and crypto.
- Fix wording on couple commits.
- Revisit checkpatch warnings.
- Moving to @chromium.org.
- patch v5:
- Adapt new crypto modules for PIE.
- Improve per-cpu commit message.
- Fix xen 32-bit build error with .quad.
- Remove extra code for ftrace.
- patch v4:
- Simplify early boot by removing global variables.
- Modify the mcount location script for __mcount_loc intead of the address
read in the ftrace implementation.
- Edit commit description to explain better where the kernel can be located.
- Streamlined the testing done on each patch proposal. Always testing
hibernation, suspend, ftrace and kprobe to ensure no regressions.
- patch v3:
- Update on message to describe longer term PIE goal.
- Minor change on ftrace if condition.
- Changed code using xchgq.
- patch v2:
- Adapt patch to work post KPTI and compiler changes
- Redo all performance testing with latest configs and compilers
- Simplify mov macro on PIE (MOVABS now)
- Reduce GOT footprint
- patch v1:
- Simplify ftrace implementation.
- Use gcc mstack-protector-guard-reg=%gs with PIE when possible.
- rfc v3:
- Use --emit-relocs instead of -pie to reduce dynamic relocation space on
mapped memory. It also simplifies the relocation process.
- Move the start the module section next to the kernel. Remove the need for
-mcmodel=large on modules. Extends module space from 1 to 2G maximum.
- Support for XEN PVH as 32-bit relocations can be ignored with
--emit-relocs.
- Support for GOT relocations previously done automatically with -pie.
- Remove need for dynamic PLT in modules.
- Support dymamic GOT for modules.
- rfc v2:
- Add support for global stack cookie while compiler default to fs without
mcmodel=kernel
- Change patch 7 to correctly jump out of the identity mapping on kexec load
preserve.
These patches make some of the changes necessary to build the kernel as
Position Independent Executable (PIE) on x86_64. Another patchset will
add the PIE option and larger architecture changes.
The patches:
- 1, 3-11: Change in assembly code to be PIE compliant.
- 2: Add a new _ASM_MOVABS macro to fetch a symbol address generically.
diffstat:
crypto/aegis128-aesni-asm.S | 6 +-
crypto/aegis128l-aesni-asm.S | 8 +--
crypto/aegis256-aesni-asm.S | 6 +-
crypto/aes-x86_64-asm_64.S | 45 ++++++++++------
crypto/aesni-intel_asm.S | 8 +--
crypto/aesni-intel_avx-x86_64.S | 3 -
crypto/camellia-aesni-avx-asm_64.S | 42 +++++++--------
crypto/camellia-aesni-avx2-asm_64.S | 44 ++++++++--------
crypto/camellia-x86_64-asm_64.S | 8 +--
crypto/cast5-avx-x86_64-asm_64.S | 50 ++++++++++--------
crypto/cast6-avx-x86_64-asm_64.S | 44 +++++++++-------
crypto/des3_ede-asm_64.S | 96 ++++++++++++++++++++++++------------
crypto/ghash-clmulni-intel_asm.S | 4 -
crypto/glue_helper-asm-avx.S | 4 -
crypto/glue_helper-asm-avx2.S | 6 +-
crypto/morus1280-avx2-asm.S | 4 -
crypto/morus1280-sse2-asm.S | 8 +--
crypto/morus640-sse2-asm.S | 6 +-
crypto/sha256-avx2-asm.S | 18 ++++--
entry/entry_64.S | 16 ++++--
include/asm/alternative.h | 6 +-
include/asm/asm.h | 1
include/asm/paravirt_types.h | 25 +++++++--
include/asm/pm-trace.h | 2
include/asm/processor.h | 6 +-
kernel/acpi/wakeup_64.S | 31 ++++++-----
kernel/head_64.S | 16 +++---
kernel/relocate_kernel_64.S | 2
power/hibernate_asm_64.S | 4 -
29 files changed, 306 insertions(+), 213 deletions(-)
Patchset is based on next-20190708.
^ permalink raw reply
* Re: [PATCH v3] cpufreq/pasemi: fix an use-after-free in pas_cpufreq_cpu_init()
From: Markus Elfring @ 2019-07-08 17:45 UTC (permalink / raw)
To: Wen Yang, linux-pm, linuxppc-dev
Cc: Cheng Shengyu, Rafael J. Wysocki, Viresh Kumar, Xue Zhihong,
Yi Wang, linux-kernel, kernel-janitors
In-Reply-To: <1562575726-17438-1-git-send-email-wen.yang99@zte.com.cn>
> @@ -204,6 +205,7 @@ static int pas_cpufreq_cpu_init(struct cpufreq_policy *policy)
> out_unmap_sdcasr:
> iounmap(sdcasr_mapbase);
> out:
> + of_node_put(cpu);
I would find the usage of a jump label like “put_node” nicer at such
a source code place.
Regards,
Markus
^ permalink raw reply
* [PATCH] tools/power/x86/intel-speed-select: Add .gitignore file
From: Prarit Bhargava @ 2019-07-08 17:31 UTC (permalink / raw)
To: linux-pm
Cc: Prarit Bhargava, Srinivas Pandruvada, Andy Shevchenko,
David Arcari
Andy, could you please add this patch to Srinivas' intel-speed-select
patchset?
Thanks,
P.
---8<---
Add a .gitignore file for build include/ and final binary.
Signed-off-by: Prarit Bhargava <prarit@redhat.com>
Cc: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Cc: Andy Shevchenko <andy.shevchenko@gmail.com>
Cc: David Arcari <darcari@redhat.com>
---
tools/power/x86/intel-speed-select/.gitignore | 2 ++
1 file changed, 2 insertions(+)
create mode 100644 tools/power/x86/intel-speed-select/.gitignore
diff --git a/tools/power/x86/intel-speed-select/.gitignore b/tools/power/x86/intel-speed-select/.gitignore
new file mode 100644
index 000000000000..f61145925ce9
--- /dev/null
+++ b/tools/power/x86/intel-speed-select/.gitignore
@@ -0,0 +1,2 @@
+include/
+intel-speed-select
--
2.21.0
^ permalink raw reply related
* Re: cpufreq notifiers break suspend -- Re: suspend broken in next-20190704 on Thinkpad X60
From: Pavel Machek @ 2019-07-08 14:13 UTC (permalink / raw)
To: Viresh Kumar
Cc: Rafael J. Wysocki, Matthias Kaehlcke, Ulf Hansson,
Rafael J. Wysocki, Linux-pm mailing list, kernel list,
Stephen Rothwell
In-Reply-To: <20190708092840.ynibtrntval6krc4@vireshk-i7>
[-- Attachment #1: Type: text/plain, Size: 2652 bytes --]
On Mon 2019-07-08 14:58:40, Viresh Kumar wrote:
> On 08-07-19, 10:28, Rafael J. Wysocki wrote:
> > Pavel has tested the latest version of the patch series AFAICS.
> >
> > The locking added by the commit in question to
> > refresh_frequency_limits() requires an update of
> > cpufreq_update_policy(), or it will deadlock in there because of the
> > lock acquired by cpufreq_cpu_get() if I haven't missed anything.
>
> Ah, looks quite straight forward.
>
> @Pavel: Can you please try this diff ?
I tried to apply it on top of current next
(d58b5ab90ee7528126fd5833df7fc5bda8331ce8, 20190708) and linux-pm-next
(1e2a4c9019eb53f62790fadf86c14a54f4cf4888), but failed due to
whitespace (?!).
Yes, symptoms would be consistent with deadlock on resume.
And yes, the patch seems to fix problem for me.
Tested-by: Pavel Machek <pavel@ucw.cz>
Pavel
> -------------------------8<-------------------------
>
> diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
> index 9f68d0f306b8..4d6043ee7834 100644
> --- a/drivers/cpufreq/cpufreq.c
> +++ b/drivers/cpufreq/cpufreq.c
> @@ -1109,16 +1109,12 @@ void refresh_frequency_limits(struct cpufreq_policy *policy)
> {
> struct cpufreq_policy new_policy;
>
> - down_write(&policy->rwsem);
> -
> if (!policy_is_inactive(policy)) {
> new_policy = *policy;
> pr_debug("updating policy for CPU %u\n", policy->cpu);
>
> cpufreq_set_policy(policy, &new_policy);
> }
> -
> - up_write(&policy->rwsem);
> }
> EXPORT_SYMBOL(refresh_frequency_limits);
>
> @@ -1128,7 +1124,9 @@ static void handle_update(struct work_struct *work)
> container_of(work, struct cpufreq_policy, update);
>
> pr_debug("handle_update for cpu %u called\n", policy->cpu);
> + down_write(&policy->rwsem);
> refresh_frequency_limits(policy);
> + up_write(&policy->rwsem);
> }
>
> -------------------------8<-------------------------
>
> Though it makes me wonder why I didn't hit this thing. I was using the
> cpu_cooling device the other day, which calls cpufreq_update_policy()
> very frequently on heat-up. And I had a hair dryer blowing over my
> board to heat it up. Lemme check that again :)
Can you test on some x86 ACPI? No dryers needed :-).
> @Rafael: You want me to send a new diff patch with Fixes tag this time
> if this works out fine ?
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 181 bytes --]
^ permalink raw reply
* [PATCH 1/3] opp: core: add regulators enable and disable
From: k.konieczny @ 2019-07-08 14:11 UTC (permalink / raw)
To: k.konieczny
Cc: Bartlomiej Zolnierkiewicz, Marek Szyprowski, Chanwoo Choi,
Krzysztof Kozlowski, Kukjin Kim, Kyungmin Park, Mark Rutland,
MyungJoo Ham, Nishanth Menon, Rob Herring, Stephen Boyd,
Viresh Kumar, devicetree, linux-arm-kernel, linux-kernel,
linux-pm, linux-samsung-soc
In-Reply-To: <20190708141140.24379-1-k.konieczny@partner.samsung.com>
From: Kamil Konieczny <k.konieczny@partner.samsung.com>
Add enable regulators to dev_pm_opp_set_regulators() and disable
regulators to dev_pm_opp_put_regulators(). This prepares for
converting exynos-bus devfreq driver to use dev_pm_opp_set_rate().
Signed-off-by: Kamil Konieczny <k.konieczny@partner.samsung.com>
---
drivers/opp/core.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/drivers/opp/core.c b/drivers/opp/core.c
index 0e7703fe733f..947cac452854 100644
--- a/drivers/opp/core.c
+++ b/drivers/opp/core.c
@@ -1580,8 +1580,19 @@ struct opp_table *dev_pm_opp_set_regulators(struct device *dev,
if (ret)
goto free_regulators;
+ for (i = 0; i < opp_table->regulator_count; i++) {
+ ret = regulator_enable(opp_table->regulators[i]);
+ if (ret < 0)
+ goto disable;
+ }
+
return opp_table;
+disable:
+ while (i != 0)
+ regulator_disable(opp_table->regulators[--i]);
+
+ i = opp_table->regulator_count;
free_regulators:
while (i != 0)
regulator_put(opp_table->regulators[--i]);
@@ -1609,6 +1620,8 @@ void dev_pm_opp_put_regulators(struct opp_table *opp_table)
/* Make sure there are no concurrent readers while updating opp_table */
WARN_ON(!list_empty(&opp_table->opp_list));
+ for (i = opp_table->regulator_count - 1; i >= 0; i--)
+ regulator_disable(opp_table->regulators[i]);
for (i = opp_table->regulator_count - 1; i >= 0; i--)
regulator_put(opp_table->regulators[i]);
--
2.22.0
^ permalink raw reply related
* [PATCH 2/3] devfreq: exynos-bus: convert to use dev_pm_opp_set_rate()
From: k.konieczny @ 2019-07-08 14:11 UTC (permalink / raw)
To: k.konieczny
Cc: Bartlomiej Zolnierkiewicz, Marek Szyprowski, Chanwoo Choi,
Krzysztof Kozlowski, Kukjin Kim, Kyungmin Park, Mark Rutland,
MyungJoo Ham, Nishanth Menon, Rob Herring, Stephen Boyd,
Viresh Kumar, devicetree, linux-arm-kernel, linux-kernel,
linux-pm, linux-samsung-soc
In-Reply-To: <20190708141140.24379-1-k.konieczny@partner.samsung.com>
From: Kamil Konieczny <k.konieczny@partner.samsung.com>
Reuse opp core code for setting bus clock and voltage. As a side
effect this allow useage of coupled regulators feature (required
for boards using Exynos5422/5800 SoCs) because dev_pm_opp_set_rate()
uses regulator_set_voltage_triplet() for setting regulator voltage
while the old code used regulator_set_voltage_tol() with fixed
tolerance. This patch also removes no longer needed parsing of DT
property "exynos,voltage-tolerance" (no Exynos devfreq DT node uses
it).
Signed-off-by: Kamil Konieczny <k.konieczny@partner.samsung.com>
---
drivers/devfreq/exynos-bus.c | 172 ++++++++++++++---------------------
1 file changed, 66 insertions(+), 106 deletions(-)
diff --git a/drivers/devfreq/exynos-bus.c b/drivers/devfreq/exynos-bus.c
index 486cc5b422f1..7fc4f76bd848 100644
--- a/drivers/devfreq/exynos-bus.c
+++ b/drivers/devfreq/exynos-bus.c
@@ -25,7 +25,6 @@
#include <linux/slab.h>
#define DEFAULT_SATURATION_RATIO 40
-#define DEFAULT_VOLTAGE_TOLERANCE 2
struct exynos_bus {
struct device *dev;
@@ -37,9 +36,9 @@ struct exynos_bus {
unsigned long curr_freq;
- struct regulator *regulator;
+ struct opp_table *opp_table;
+
struct clk *clk;
- unsigned int voltage_tolerance;
unsigned int ratio;
};
@@ -99,56 +98,25 @@ static int exynos_bus_target(struct device *dev, unsigned long *freq, u32 flags)
{
struct exynos_bus *bus = dev_get_drvdata(dev);
struct dev_pm_opp *new_opp;
- unsigned long old_freq, new_freq, new_volt, tol;
int ret = 0;
-
- /* Get new opp-bus instance according to new bus clock */
+ /*
+ * New frequency for bus may not be exactly matched to opp, adjust
+ * *freq to correct value.
+ */
new_opp = devfreq_recommended_opp(dev, freq, flags);
if (IS_ERR(new_opp)) {
dev_err(dev, "failed to get recommended opp instance\n");
return PTR_ERR(new_opp);
}
- new_freq = dev_pm_opp_get_freq(new_opp);
- new_volt = dev_pm_opp_get_voltage(new_opp);
dev_pm_opp_put(new_opp);
- old_freq = bus->curr_freq;
-
- if (old_freq == new_freq)
- return 0;
- tol = new_volt * bus->voltage_tolerance / 100;
-
/* Change voltage and frequency according to new OPP level */
mutex_lock(&bus->lock);
+ ret = dev_pm_opp_set_rate(dev, *freq);
+ if (!ret)
+ bus->curr_freq = *freq;
- if (old_freq < new_freq) {
- ret = regulator_set_voltage_tol(bus->regulator, new_volt, tol);
- if (ret < 0) {
- dev_err(bus->dev, "failed to set voltage\n");
- goto out;
- }
- }
-
- ret = clk_set_rate(bus->clk, new_freq);
- if (ret < 0) {
- dev_err(dev, "failed to change clock of bus\n");
- clk_set_rate(bus->clk, old_freq);
- goto out;
- }
-
- if (old_freq > new_freq) {
- ret = regulator_set_voltage_tol(bus->regulator, new_volt, tol);
- if (ret < 0) {
- dev_err(bus->dev, "failed to set voltage\n");
- goto out;
- }
- }
- bus->curr_freq = new_freq;
-
- dev_dbg(dev, "Set the frequency of bus (%luHz -> %luHz, %luHz)\n",
- old_freq, new_freq, clk_get_rate(bus->clk));
-out:
mutex_unlock(&bus->lock);
return ret;
@@ -194,10 +162,11 @@ static void exynos_bus_exit(struct device *dev)
if (ret < 0)
dev_warn(dev, "failed to disable the devfreq-event devices\n");
- if (bus->regulator)
- regulator_disable(bus->regulator);
+ if (bus->opp_table)
+ dev_pm_opp_put_regulators(bus->opp_table);
dev_pm_opp_of_remove_table(dev);
+
clk_disable_unprepare(bus->clk);
}
@@ -209,39 +178,26 @@ static int exynos_bus_passive_target(struct device *dev, unsigned long *freq,
{
struct exynos_bus *bus = dev_get_drvdata(dev);
struct dev_pm_opp *new_opp;
- unsigned long old_freq, new_freq;
- int ret = 0;
+ int ret;
- /* Get new opp-bus instance according to new bus clock */
+ /*
+ * New frequency for bus may not be exactly matched to opp, adjust
+ * *freq to correct value.
+ */
new_opp = devfreq_recommended_opp(dev, freq, flags);
if (IS_ERR(new_opp)) {
dev_err(dev, "failed to get recommended opp instance\n");
return PTR_ERR(new_opp);
}
- new_freq = dev_pm_opp_get_freq(new_opp);
dev_pm_opp_put(new_opp);
- old_freq = bus->curr_freq;
-
- if (old_freq == new_freq)
- return 0;
-
/* Change the frequency according to new OPP level */
mutex_lock(&bus->lock);
+ ret = dev_pm_opp_set_rate(dev, *freq);
+ if (!ret)
+ bus->curr_freq = *freq;
- ret = clk_set_rate(bus->clk, new_freq);
- if (ret < 0) {
- dev_err(dev, "failed to set the clock of bus\n");
- goto out;
- }
-
- *freq = new_freq;
- bus->curr_freq = new_freq;
-
- dev_dbg(dev, "Set the frequency of bus (%luHz -> %luHz, %luHz)\n",
- old_freq, new_freq, clk_get_rate(bus->clk));
-out:
mutex_unlock(&bus->lock);
return ret;
@@ -259,20 +215,7 @@ static int exynos_bus_parent_parse_of(struct device_node *np,
struct exynos_bus *bus)
{
struct device *dev = bus->dev;
- int i, ret, count, size;
-
- /* Get the regulator to provide each bus with the power */
- bus->regulator = devm_regulator_get(dev, "vdd");
- if (IS_ERR(bus->regulator)) {
- dev_err(dev, "failed to get VDD regulator\n");
- return PTR_ERR(bus->regulator);
- }
-
- ret = regulator_enable(bus->regulator);
- if (ret < 0) {
- dev_err(dev, "failed to enable VDD regulator\n");
- return ret;
- }
+ int i, count, size;
/*
* Get the devfreq-event devices to get the current utilization of
@@ -281,24 +224,20 @@ static int exynos_bus_parent_parse_of(struct device_node *np,
count = devfreq_event_get_edev_count(dev);
if (count < 0) {
dev_err(dev, "failed to get the count of devfreq-event dev\n");
- ret = count;
- goto err_regulator;
+ return count;
}
+
bus->edev_count = count;
size = sizeof(*bus->edev) * count;
bus->edev = devm_kzalloc(dev, size, GFP_KERNEL);
- if (!bus->edev) {
- ret = -ENOMEM;
- goto err_regulator;
- }
+ if (!bus->edev)
+ return -ENOMEM;
for (i = 0; i < count; i++) {
bus->edev[i] = devfreq_event_get_edev_by_phandle(dev, i);
- if (IS_ERR(bus->edev[i])) {
- ret = -EPROBE_DEFER;
- goto err_regulator;
- }
+ if (IS_ERR(bus->edev[i]))
+ return -EPROBE_DEFER;
}
/*
@@ -314,22 +253,15 @@ static int exynos_bus_parent_parse_of(struct device_node *np,
if (of_property_read_u32(np, "exynos,saturation-ratio", &bus->ratio))
bus->ratio = DEFAULT_SATURATION_RATIO;
- if (of_property_read_u32(np, "exynos,voltage-tolerance",
- &bus->voltage_tolerance))
- bus->voltage_tolerance = DEFAULT_VOLTAGE_TOLERANCE;
-
return 0;
-
-err_regulator:
- regulator_disable(bus->regulator);
-
- return ret;
}
static int exynos_bus_parse_of(struct device_node *np,
- struct exynos_bus *bus)
+ struct exynos_bus *bus, bool passive)
{
struct device *dev = bus->dev;
+ struct opp_table *opp_table;
+ const char *vdd = "vdd";
struct dev_pm_opp *opp;
unsigned long rate;
int ret;
@@ -347,11 +279,22 @@ static int exynos_bus_parse_of(struct device_node *np,
return ret;
}
+ if (!passive) {
+ opp_table = dev_pm_opp_set_regulators(dev, &vdd, 1);
+ if (IS_ERR(opp_table)) {
+ ret = PTR_ERR(opp_table);
+ dev_err(dev, "failed to set regulators %d\n", ret);
+ goto err_clk;
+ }
+
+ bus->opp_table = opp_table;
+ }
+
/* Get the freq and voltage from OPP table to scale the bus freq */
ret = dev_pm_opp_of_add_table(dev);
if (ret < 0) {
dev_err(dev, "failed to get OPP table\n");
- goto err_clk;
+ goto err_regulator;
}
rate = clk_get_rate(bus->clk);
@@ -362,6 +305,7 @@ static int exynos_bus_parse_of(struct device_node *np,
ret = PTR_ERR(opp);
goto err_opp;
}
+
bus->curr_freq = dev_pm_opp_get_freq(opp);
dev_pm_opp_put(opp);
@@ -369,6 +313,13 @@ static int exynos_bus_parse_of(struct device_node *np,
err_opp:
dev_pm_opp_of_remove_table(dev);
+
+err_regulator:
+ if (bus->opp_table) {
+ dev_pm_opp_put_regulators(bus->opp_table);
+ bus->opp_table = NULL;
+ }
+
err_clk:
clk_disable_unprepare(bus->clk);
@@ -386,6 +337,7 @@ static int exynos_bus_probe(struct platform_device *pdev)
struct exynos_bus *bus;
int ret, max_state;
unsigned long min_freq, max_freq;
+ bool passive = false;
if (!np) {
dev_err(dev, "failed to find devicetree node\n");
@@ -395,12 +347,18 @@ static int exynos_bus_probe(struct platform_device *pdev)
bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL);
if (!bus)
return -ENOMEM;
+
mutex_init(&bus->lock);
bus->dev = &pdev->dev;
platform_set_drvdata(pdev, bus);
+ node = of_parse_phandle(dev->of_node, "devfreq", 0);
+ if (node) {
+ of_node_put(node);
+ passive = true;
+ }
/* Parse the device-tree to get the resource information */
- ret = exynos_bus_parse_of(np, bus);
+ ret = exynos_bus_parse_of(np, bus, passive);
if (ret < 0)
return ret;
@@ -410,13 +368,10 @@ static int exynos_bus_probe(struct platform_device *pdev)
goto err;
}
- node = of_parse_phandle(dev->of_node, "devfreq", 0);
- if (node) {
- of_node_put(node);
+ if (passive)
goto passive;
- } else {
- ret = exynos_bus_parent_parse_of(np, bus);
- }
+
+ ret = exynos_bus_parent_parse_of(np, bus);
if (ret < 0)
goto err;
@@ -509,6 +464,11 @@ static int exynos_bus_probe(struct platform_device *pdev)
err:
dev_pm_opp_of_remove_table(dev);
+ if (bus->opp_table) {
+ dev_pm_opp_put_regulators(bus->opp_table);
+ bus->opp_table = NULL;
+ }
+
clk_disable_unprepare(bus->clk);
return ret;
--
2.22.0
^ permalink raw reply related
* [PATCH 3/3] ARM: dts: exynos: add initial data for coupled regulators for Exynos5422/5800
From: k.konieczny @ 2019-07-08 14:11 UTC (permalink / raw)
To: k.konieczny
Cc: Marek Szyprowski, Bartlomiej Zolnierkiewicz, Chanwoo Choi,
Krzysztof Kozlowski, Kukjin Kim, Kyungmin Park, Mark Rutland,
MyungJoo Ham, Nishanth Menon, Rob Herring, Stephen Boyd,
Viresh Kumar, devicetree, linux-arm-kernel, linux-kernel,
linux-pm, linux-samsung-soc
In-Reply-To: <20190708141140.24379-1-k.konieczny@partner.samsung.com>
From: Marek Szyprowski <m.szyprowski@samsung.com>
Declare Exynos5422/5800 voltage ranges for opp points for big cpu core and
bus wcore and couple their voltage supllies as vdd_arm and vdd_int should
be in 300mV range.
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Kamil Konieczny <k.konieczny@partner.samsung.com>
---
arch/arm/boot/dts/exynos5420.dtsi | 34 +++++++++----------
arch/arm/boot/dts/exynos5422-odroid-core.dtsi | 4 +++
arch/arm/boot/dts/exynos5800-peach-pi.dts | 4 +++
arch/arm/boot/dts/exynos5800.dtsi | 32 ++++++++---------
4 files changed, 41 insertions(+), 33 deletions(-)
diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index 5fb2326875dc..0cbf74750553 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -48,62 +48,62 @@
opp-shared;
opp-1800000000 {
opp-hz = /bits/ 64 <1800000000>;
- opp-microvolt = <1250000>;
+ opp-microvolt = <1250000 1250000 1500000>;
clock-latency-ns = <140000>;
};
opp-1700000000 {
opp-hz = /bits/ 64 <1700000000>;
- opp-microvolt = <1212500>;
+ opp-microvolt = <1212500 1212500 1500000>;
clock-latency-ns = <140000>;
};
opp-1600000000 {
opp-hz = /bits/ 64 <1600000000>;
- opp-microvolt = <1175000>;
+ opp-microvolt = <1175000 1175000 1500000>;
clock-latency-ns = <140000>;
};
opp-1500000000 {
opp-hz = /bits/ 64 <1500000000>;
- opp-microvolt = <1137500>;
+ opp-microvolt = <1137500 1137500 1500000>;
clock-latency-ns = <140000>;
};
opp-1400000000 {
opp-hz = /bits/ 64 <1400000000>;
- opp-microvolt = <1112500>;
+ opp-microvolt = <1112500 1112500 1500000>;
clock-latency-ns = <140000>;
};
opp-1300000000 {
opp-hz = /bits/ 64 <1300000000>;
- opp-microvolt = <1062500>;
+ opp-microvolt = <1062500 1062500 1500000>;
clock-latency-ns = <140000>;
};
opp-1200000000 {
opp-hz = /bits/ 64 <1200000000>;
- opp-microvolt = <1037500>;
+ opp-microvolt = <1037500 1037500 1500000>;
clock-latency-ns = <140000>;
};
opp-1100000000 {
opp-hz = /bits/ 64 <1100000000>;
- opp-microvolt = <1012500>;
+ opp-microvolt = <1012500 1012500 1500000>;
clock-latency-ns = <140000>;
};
opp-1000000000 {
opp-hz = /bits/ 64 <1000000000>;
- opp-microvolt = < 987500>;
+ opp-microvolt = < 987500 987500 1500000>;
clock-latency-ns = <140000>;
};
opp-900000000 {
opp-hz = /bits/ 64 <900000000>;
- opp-microvolt = < 962500>;
+ opp-microvolt = < 962500 962500 1500000>;
clock-latency-ns = <140000>;
};
opp-800000000 {
opp-hz = /bits/ 64 <800000000>;
- opp-microvolt = < 937500>;
+ opp-microvolt = < 937500 937500 1500000>;
clock-latency-ns = <140000>;
};
opp-700000000 {
opp-hz = /bits/ 64 <700000000>;
- opp-microvolt = < 912500>;
+ opp-microvolt = < 912500 912500 1500000>;
clock-latency-ns = <140000>;
};
};
@@ -1100,23 +1100,23 @@
opp00 {
opp-hz = /bits/ 64 <84000000>;
- opp-microvolt = <925000>;
+ opp-microvolt = <925000 925000 1400000>;
};
opp01 {
opp-hz = /bits/ 64 <111000000>;
- opp-microvolt = <950000>;
+ opp-microvolt = <950000 950000 1400000>;
};
opp02 {
opp-hz = /bits/ 64 <222000000>;
- opp-microvolt = <950000>;
+ opp-microvolt = <950000 950000 1400000>;
};
opp03 {
opp-hz = /bits/ 64 <333000000>;
- opp-microvolt = <950000>;
+ opp-microvolt = <950000 950000 1400000>;
};
opp04 {
opp-hz = /bits/ 64 <400000000>;
- opp-microvolt = <987500>;
+ opp-microvolt = <987500 987500 1400000>;
};
};
diff --git a/arch/arm/boot/dts/exynos5422-odroid-core.dtsi b/arch/arm/boot/dts/exynos5422-odroid-core.dtsi
index 25d95de15c9b..65d094256b54 100644
--- a/arch/arm/boot/dts/exynos5422-odroid-core.dtsi
+++ b/arch/arm/boot/dts/exynos5422-odroid-core.dtsi
@@ -428,6 +428,8 @@
regulator-max-microvolt = <1500000>;
regulator-always-on;
regulator-boot-on;
+ regulator-coupled-with = <&buck3_reg>;
+ regulator-coupled-max-spread = <300000>;
};
buck3_reg: BUCK3 {
@@ -436,6 +438,8 @@
regulator-max-microvolt = <1400000>;
regulator-always-on;
regulator-boot-on;
+ regulator-coupled-with = <&buck2_reg>;
+ regulator-coupled-max-spread = <300000>;
};
buck4_reg: BUCK4 {
diff --git a/arch/arm/boot/dts/exynos5800-peach-pi.dts b/arch/arm/boot/dts/exynos5800-peach-pi.dts
index e0f470fe54c8..5c1e965ed7e9 100644
--- a/arch/arm/boot/dts/exynos5800-peach-pi.dts
+++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts
@@ -257,6 +257,8 @@
regulator-always-on;
regulator-boot-on;
regulator-ramp-delay = <12500>;
+ regulator-coupled-with = <&buck3_reg>;
+ regulator-coupled-max-spread = <300000>;
regulator-state-mem {
regulator-off-in-suspend;
};
@@ -269,6 +271,8 @@
regulator-always-on;
regulator-boot-on;
regulator-ramp-delay = <12500>;
+ regulator-coupled-with = <&buck2_reg>;
+ regulator-coupled-max-spread = <300000>;
regulator-state-mem {
regulator-off-in-suspend;
};
diff --git a/arch/arm/boot/dts/exynos5800.dtsi b/arch/arm/boot/dts/exynos5800.dtsi
index 57d3b319fd65..2a74735d161c 100644
--- a/arch/arm/boot/dts/exynos5800.dtsi
+++ b/arch/arm/boot/dts/exynos5800.dtsi
@@ -22,61 +22,61 @@
&cluster_a15_opp_table {
opp-1700000000 {
- opp-microvolt = <1250000>;
+ opp-microvolt = <1250000 1250000 1500000>;
};
opp-1600000000 {
- opp-microvolt = <1250000>;
+ opp-microvolt = <1250000 1250000 1500000>;
};
opp-1500000000 {
- opp-microvolt = <1100000>;
+ opp-microvolt = <1100000 1100000 1500000>;
};
opp-1400000000 {
- opp-microvolt = <1100000>;
+ opp-microvolt = <1100000 1100000 1500000>;
};
opp-1300000000 {
- opp-microvolt = <1100000>;
+ opp-microvolt = <1100000 1100000 1500000>;
};
opp-1200000000 {
- opp-microvolt = <1000000>;
+ opp-microvolt = <1000000 1000000 1500000>;
};
opp-1100000000 {
- opp-microvolt = <1000000>;
+ opp-microvolt = <1000000 1000000 1500000>;
};
opp-1000000000 {
- opp-microvolt = <1000000>;
+ opp-microvolt = <1000000 1000000 1500000>;
};
opp-900000000 {
- opp-microvolt = <1000000>;
+ opp-microvolt = <1000000 1000000 1500000>;
};
opp-800000000 {
- opp-microvolt = <900000>;
+ opp-microvolt = <900000 900000 1500000>;
};
opp-700000000 {
- opp-microvolt = <900000>;
+ opp-microvolt = <900000 900000 1500000>;
};
opp-600000000 {
opp-hz = /bits/ 64 <600000000>;
- opp-microvolt = <900000>;
+ opp-microvolt = <900000 900000 1500000>;
clock-latency-ns = <140000>;
};
opp-500000000 {
opp-hz = /bits/ 64 <500000000>;
- opp-microvolt = <900000>;
+ opp-microvolt = <900000 900000 1500000>;
clock-latency-ns = <140000>;
};
opp-400000000 {
opp-hz = /bits/ 64 <400000000>;
- opp-microvolt = <900000>;
+ opp-microvolt = <900000 900000 1500000>;
clock-latency-ns = <140000>;
};
opp-300000000 {
opp-hz = /bits/ 64 <300000000>;
- opp-microvolt = <900000>;
+ opp-microvolt = <900000 900000 1500000>;
clock-latency-ns = <140000>;
};
opp-200000000 {
opp-hz = /bits/ 64 <200000000>;
- opp-microvolt = <900000>;
+ opp-microvolt = <900000 900000 1500000>;
clock-latency-ns = <140000>;
};
};
--
2.22.0
^ permalink raw reply related
* [PATCH 0/3] add coupled regulators for Exynos5422/5800
From: k.konieczny @ 2019-07-08 14:11 UTC (permalink / raw)
To: k.konieczny
Cc: Bartlomiej Zolnierkiewicz, Marek Szyprowski, Chanwoo Choi,
Krzysztof Kozlowski, Kukjin Kim, Kyungmin Park, Mark Rutland,
MyungJoo Ham, Nishanth Menon, Rob Herring, Stephen Boyd,
Viresh Kumar, devicetree, linux-arm-kernel, linux-kernel,
linux-pm, linux-samsung-soc
In-Reply-To: <CGME20190708141158eucas1p17d4b50978dbe1e5c876ce6d8f433cc95@eucas1p1.samsung.com>
From: Kamil Konieczny <k.konieczny@partner.samsung.com>
Hi,
The main purpose of this patch series is to add coupled regulators for
Exynos5422/5800 to keep constrain on voltage difference between vdd_arm
and vdd_int to be at most 300mV. In exynos-bus instead of using
regulator_set_voltage_tol() with default voltage tolerance it should be
used regulator_set_voltage_triplet() with volatege range, and this is
already present in opp/core.c code, so it can be reused. While at this,
move setting regulators into opp/core.
This patchset was tested on Odroid XU3.
The last patch depends on two previous.
Regards,
Kamil
Kamil Konieczny (2):
opp: core: add regulators enable and disable
devfreq: exynos-bus: convert to use dev_pm_opp_set_rate()
Marek Szyprowski (1):
ARM: dts: exynos: add initial data for coupled regulators for
Exynos5422/5800
arch/arm/boot/dts/exynos5420.dtsi | 34 ++--
arch/arm/boot/dts/exynos5422-odroid-core.dtsi | 4 +
arch/arm/boot/dts/exynos5800-peach-pi.dts | 4 +
arch/arm/boot/dts/exynos5800.dtsi | 32 ++--
drivers/devfreq/exynos-bus.c | 172 +++++++-----------
drivers/opp/core.c | 13 ++
6 files changed, 120 insertions(+), 139 deletions(-)
--
2.22.0
^ permalink raw reply
* Re: [RFC PATCH v2 0/5] sched/cpufreq: Make schedutil energy aware
From: Douglas Raillard @ 2019-07-08 13:49 UTC (permalink / raw)
To: Patrick Bellasi
Cc: Peter Zijlstra, linux-kernel, linux-pm, mingo, rjw, viresh.kumar,
quentin.perret, dietmar.eggemann
In-Reply-To: <20190708111348.o6o63jisbukuk64d@e110439-lin>
On 7/8/19 12:13 PM, Patrick Bellasi wrote:
> On 03-Jul 14:38, Douglas Raillard wrote:
>> Hi Peter,
>>
>> On 7/2/19 4:44 PM, Peter Zijlstra wrote:
>>> On Thu, Jun 27, 2019 at 06:15:58PM +0100, Douglas RAILLARD wrote:
>>>> Make schedutil cpufreq governor energy-aware.
>>>>
>>>> - patch 1 introduces a function to retrieve a frequency given a base
>>>> frequency and an energy cost margin.
>>>> - patch 2 links Energy Model perf_domain to sugov_policy.
>>>> - patch 3 updates get_next_freq() to make use of the Energy Model.
>>>
>>>>
>>>> 1) Selecting the highest possible frequency for a given cost. Some
>>>> platforms can have lower frequencies that are less efficient than
>>>> higher ones, in which case they should be skipped for most purposes.
>>>> They can still be useful to give more freedom to thermal throttling
>>>> mechanisms, but not under normal circumstances.
>>>> note: the EM framework will warn about such OPPs "hertz/watts ratio
>>>> non-monotonically decreasing"
>>>
>>> Humm, for some reason I was thinking we explicitly skipped those OPPs
>>> and they already weren't used.
>>>
>>> This isn't in fact so, and these first few patches make it so?
>>
>> That's correct, the cost information about each OPP has been introduced recently in mainline
>> by the energy model series. Without that info, the only way to skip them that comes to my
>> mind is to set a policy min frequency, since these inefficient OPPs are usually located
>> at the lower end.
>
> Perhaps it's also worth to point out that the alternative approach you
> point out above is a system wide solution.
>
> While, the ramp_boost thingy you propose, it's a more fine grained
> mechanisms which could be extended in the future to have a per-task
> side. IOW, it could contribute to have better user-space hints, for
> example to ramp_boost more certain tasks and not others.
ramp_boost and the situation you describe are more what solves point 2) (which has been cut out in that answer),
this point "1)" is really just about avoiding selection of some OPPs, regardless of task util. IOW, it's better to
skip the OPPs we talk about here, and race to idle at a higher OPP regardless of what the task need.
> Best,
> Patrick
>
Cheers,
Douglas
^ permalink raw reply
* Re: [RFC PATCH v2 0/5] sched/cpufreq: Make schedutil energy aware
From: Douglas Raillard @ 2019-07-08 13:46 UTC (permalink / raw)
To: Patrick Bellasi
Cc: Peter Zijlstra, linux-kernel, linux-pm, mingo, rjw, viresh.kumar,
quentin.perret, dietmar.eggemann
In-Reply-To: <20190708110904.ecrlr4p77n4r6qzk@e110439-lin>
Hi Patrick,
On 7/8/19 12:09 PM, Patrick Bellasi wrote:
> On 03-Jul 17:36, Douglas Raillard wrote:
>> On 7/2/19 4:51 PM, Peter Zijlstra wrote:
>>> On Thu, Jun 27, 2019 at 06:15:58PM +0100, Douglas RAILLARD wrote:
>
> [...]
>
>>> I'm not immediately seeing how it is transient; that is, PELT has a
>>> wobble in it's steady state, is that accounted for?
>>>
>>
>> The transient-ness of the ramp boost I'm introducing comes from the fact that for a
>> periodic task at steady state, task_ue.enqueued <= task_u when the task is executing.
> ^^^^^^^^^^^^^^^
>
> I find your above "at steady state" a bit confusing.
>
> The condition "task_ue.enqueue <= task_u" is true only for the first
> task's big activation after a series of small activations, e.g. a task
> switching from 20% to 70%.
I actually made a typo and meant "task_u <= task_ue.enqueue". The rest of the paragraph
is aligned with that condition, sorry for the confusion.
> That's the transient stat you refer to, isn't it?
>
>> That is because task_ue.enqueued is sampled at dequeue time, precisely at the moment
>> at which task_u is reaching its max for that task.
>
> Right, so in the example above we will have enqueued=20% while task_u
> is going above to converge towards 70%
>
>> Since we only take into account positive boosts, ramp boost will
>> only have an impact in the "increase transients".
>
> Right.
>
> I think Peter was referring to the smallish wobbles we see when the
> task already converged to 70%. If that's the case I would say they are
> already fully covered also by the current util_est.
Yes, that's covered by the "task_u <= task_ue.enqueue" condition, with task_ue.enqueued
not having any of these "mid freq" content that we call wobble here.
Util est enqueued acts as an adaptive filter that kills frequencies higher than 1/task_period,
task_period being the delta between the two previous "enqueue events". All what's (mostly) remaining
after that is util variation of larger periods, with a positive shift that increases with
the task period (mean(enqueued) = mean(util_avg) + f(task_period)).
> You are also correct in pointing out that in the steady state
> ramp_boost will not be triggered in that steady state.
>
> IMU, that's for two main reasons:
> a) it's very likely that enqueued <= util_avg
> b) even in case enqueued should turn out to be _slightly_ bigger then
> util_avg, the corresponding (proportional) ramp_boost would be so
> tiny to not have any noticeable effect on OPP selection.
>
> Am I correct on point b) above?
Assuming you meant "util_avg slightly bigger than enqueued" (which is when boosting triggers),
then yes since ramp_boost effect is proportional to "task_ue.enqueue - task_u". It makes it robust
against that.
>
> Could you maybe come up with some experimental numbers related to that
> case specifically?
With:
* an rt-app task ramping up from 5% to 75% util in one big step. The whole cycle is 0.6s long
(0.3s at 5% followed by 0.3s at 75%). This cycle is repeated 20 times and the average of
boosting is taken.
* a hikey 960 (this impact the frequency at which the test runs at the beginning of 75% phase,
which impacts the number of missed activations before the util ramped up).
* assuming an OPP exists for each util value (i.e. 1024 OPPs, so the effect
of boost on consumption is not impacted by OPP capacities granularity)
Then the boosting feature would increase the average power consumption by 3.1%, out of which 0.12% can
be considered "spurious boosting" due to the util taking some time to really converge to its
steady state value. In practice, the impact of small boosts will be even lower since they will less likely
trigger the selection of a high OPP due to OPP capacity granularity > 1 util unit.
>
> Best,
> Patrick
>
Best regards,
Douglas
^ permalink raw reply
* [PATCH] power: reset: nvmem-reboot-mode: add CONFIG_OF dependency
From: Arnd Bergmann @ 2019-07-08 12:52 UTC (permalink / raw)
To: Sebastian Reichel
Cc: Arnd Bergmann, Nandor Han, Sebastian Reichel, Greg Kroah-Hartman,
Thomas Gleixner, linux-pm, linux-kernel
Without CONFIG_OF, we get a build failure in the reboot-mode
implementation:
drivers/power/reset/reboot-mode.c: In function 'reboot_mode_register':
drivers/power/reset/reboot-mode.c:72:2: error: implicit declaration of function 'for_each_property_of_node'; did you mean 'for_each_child_of_node'? [-Werror=implicit-function-declaration]
for_each_property_of_node(np, prop) {
Add a Kconfig dependency like we have for the other users of
CONFIG_REBOOT_MODE.
Fixes: 7a78a7f7695b ("power: reset: nvmem-reboot-mode: use NVMEM as reboot mode write interface")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
drivers/power/reset/Kconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index 8dfb105db391..a564237278ff 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -248,6 +248,7 @@ config POWER_RESET_SC27XX
config NVMEM_REBOOT_MODE
tristate "Generic NVMEM reboot mode driver"
+ depends on OF
select REBOOT_MODE
help
Say y here will enable reboot mode driver. This will
--
2.20.0
^ permalink raw reply related
* [PATCH] drivers: thermal: processor_thermal: mark pm function __maybe_unused
From: Arnd Bergmann @ 2019-07-08 12:47 UTC (permalink / raw)
To: Zhang Rui, Eduardo Valentin
Cc: Arnd Bergmann, Srinivas Pandruvada, Daniel Lezcano, linux-pm,
linux-kernel
Without CONFIG_PM, we get a harmless warning:
drivers/thermal/intel/int340x_thermal/processor_thermal_device.c:446:12: error: 'proc_thermal_resume' defined but not used [-Werror=unused-function]
static int proc_thermal_resume(struct device *dev)
Mark it __maybe_unused to shut up the warning.
Fixes: aaba9791fbb4 ("drivers: thermal: processor_thermal: Read PPCC on resume")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
.../thermal/intel/int340x_thermal/processor_thermal_device.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c
index a3210f09f366..5ce639a99330 100644
--- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c
+++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c
@@ -443,7 +443,7 @@ static void proc_thermal_pci_remove(struct pci_dev *pdev)
pci_disable_device(pdev);
}
-static int proc_thermal_resume(struct device *dev)
+static int __maybe_unused proc_thermal_resume(struct device *dev)
{
struct proc_thermal_device *proc_dev;
--
2.20.0
^ permalink raw reply related
* [PATCH 13/14] thermal: rcar_gen3_thermal: Replace devm_add_action() followed by failure action with devm_add_action_or_reset()
From: Fuqian Huang @ 2019-07-08 12:34 UTC (permalink / raw)
Cc: Zhang Rui, Eduardo Valentin, linux-pm, linux-kernel, Fuqian Huang
devm_add_action_or_reset() is introduced as a helper function which
internally calls devm_add_action(). If devm_add_action() fails
then it will execute the action mentioned and return the error code.
This reduce source code size (avoid writing the action twice)
and reduce the likelyhood of bugs.
Signed-off-by: Fuqian Huang <huangfq.daxian@gmail.com>
---
drivers/thermal/rcar_gen3_thermal.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/thermal/rcar_gen3_thermal.c b/drivers/thermal/rcar_gen3_thermal.c
index a56463308694..755d2b5bd2c2 100644
--- a/drivers/thermal/rcar_gen3_thermal.c
+++ b/drivers/thermal/rcar_gen3_thermal.c
@@ -443,9 +443,8 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
if (ret)
goto error_unregister;
- ret = devm_add_action(dev, rcar_gen3_hwmon_action, zone);
+ ret = devm_add_action_or_reset(dev, rcar_gen3_hwmon_action, zone);
if (ret) {
- rcar_gen3_hwmon_action(zone);
goto error_unregister;
}
--
2.11.0
^ permalink raw reply related
* [PATCH 04/14] power: supply: sc27xx: Replace devm_add_action() followed by failure action with devm_add_action_or_reset()
From: Fuqian Huang @ 2019-07-08 12:32 UTC (permalink / raw)
Cc: Sebastian Reichel, linux-pm, linux-kernel, Fuqian Huang
devm_add_action_or_reset() is introduced as a helper function which
internally calls devm_add_action(). If devm_add_action() fails
then it will execute the action mentioned and return the error code.
This reduce source code size (avoid writing the action twice)
and reduce the likelyhood of bugs.
Signed-off-by: Fuqian Huang <huangfq.daxian@gmail.com>
---
drivers/power/supply/sc27xx_fuel_gauge.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/power/supply/sc27xx_fuel_gauge.c b/drivers/power/supply/sc27xx_fuel_gauge.c
index 9c184d80088b..58b2970cd359 100644
--- a/drivers/power/supply/sc27xx_fuel_gauge.c
+++ b/drivers/power/supply/sc27xx_fuel_gauge.c
@@ -1023,9 +1023,8 @@ static int sc27xx_fgu_probe(struct platform_device *pdev)
return ret;
}
- ret = devm_add_action(dev, sc27xx_fgu_disable, data);
+ ret = devm_add_action_or_reset(dev, sc27xx_fgu_disable, data);
if (ret) {
- sc27xx_fgu_disable(data);
dev_err(dev, "failed to add fgu disable action\n");
return ret;
}
--
2.11.0
^ permalink raw reply related
* [PATCH 03/14] power: supply: sc27xx: Introduce local variable 'struct device *dev'
From: Fuqian Huang @ 2019-07-08 12:32 UTC (permalink / raw)
Cc: Sebastian Reichel, linux-pm, linux-kernel, Fuqian Huang
Introduce local variable 'struct device *dev' and use it instead of
dereferencing it repeatly.
Signed-off-by: Fuqian Huang <huangfq.daxian@gmail.com>
---
drivers/power/supply/sc27xx_fuel_gauge.c | 47 ++++++++++++++++----------------
1 file changed, 24 insertions(+), 23 deletions(-)
diff --git a/drivers/power/supply/sc27xx_fuel_gauge.c b/drivers/power/supply/sc27xx_fuel_gauge.c
index 24895cc3b41e..9c184d80088b 100644
--- a/drivers/power/supply/sc27xx_fuel_gauge.c
+++ b/drivers/power/supply/sc27xx_fuel_gauge.c
@@ -957,81 +957,82 @@ static int sc27xx_fgu_hw_init(struct sc27xx_fgu_data *data)
static int sc27xx_fgu_probe(struct platform_device *pdev)
{
- struct device_node *np = pdev->dev.of_node;
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
struct power_supply_config fgu_cfg = { };
struct sc27xx_fgu_data *data;
int ret, irq;
- data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
- data->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ data->regmap = dev_get_regmap(dev->parent, NULL);
if (!data->regmap) {
- dev_err(&pdev->dev, "failed to get regmap\n");
+ dev_err(dev, "failed to get regmap\n");
return -ENODEV;
}
- ret = device_property_read_u32(&pdev->dev, "reg", &data->base);
+ ret = device_property_read_u32(dev, "reg", &data->base);
if (ret) {
- dev_err(&pdev->dev, "failed to get fgu address\n");
+ dev_err(dev, "failed to get fgu address\n");
return ret;
}
- data->channel = devm_iio_channel_get(&pdev->dev, "bat-temp");
+ data->channel = devm_iio_channel_get(dev, "bat-temp");
if (IS_ERR(data->channel)) {
- dev_err(&pdev->dev, "failed to get IIO channel\n");
+ dev_err(dev, "failed to get IIO channel\n");
return PTR_ERR(data->channel);
}
- data->charge_chan = devm_iio_channel_get(&pdev->dev, "charge-vol");
+ data->charge_chan = devm_iio_channel_get(dev, "charge-vol");
if (IS_ERR(data->charge_chan)) {
- dev_err(&pdev->dev, "failed to get charge IIO channel\n");
+ dev_err(dev, "failed to get charge IIO channel\n");
return PTR_ERR(data->charge_chan);
}
- data->gpiod = devm_gpiod_get(&pdev->dev, "bat-detect", GPIOD_IN);
+ data->gpiod = devm_gpiod_get(dev, "bat-detect", GPIOD_IN);
if (IS_ERR(data->gpiod)) {
- dev_err(&pdev->dev, "failed to get battery detection GPIO\n");
+ dev_err(dev, "failed to get battery detection GPIO\n");
return PTR_ERR(data->gpiod);
}
ret = gpiod_get_value_cansleep(data->gpiod);
if (ret < 0) {
- dev_err(&pdev->dev, "failed to get gpio state\n");
+ dev_err(dev, "failed to get gpio state\n");
return ret;
}
data->bat_present = !!ret;
mutex_init(&data->lock);
- data->dev = &pdev->dev;
+ data->dev = dev;
platform_set_drvdata(pdev, data);
fgu_cfg.drv_data = data;
fgu_cfg.of_node = np;
- data->battery = devm_power_supply_register(&pdev->dev, &sc27xx_fgu_desc,
+ data->battery = devm_power_supply_register(dev, &sc27xx_fgu_desc,
&fgu_cfg);
if (IS_ERR(data->battery)) {
- dev_err(&pdev->dev, "failed to register power supply\n");
+ dev_err(dev, "failed to register power supply\n");
return PTR_ERR(data->battery);
}
ret = sc27xx_fgu_hw_init(data);
if (ret) {
- dev_err(&pdev->dev, "failed to initialize fgu hardware\n");
+ dev_err(dev, "failed to initialize fgu hardware\n");
return ret;
}
- ret = devm_add_action(&pdev->dev, sc27xx_fgu_disable, data);
+ ret = devm_add_action(dev, sc27xx_fgu_disable, data);
if (ret) {
sc27xx_fgu_disable(data);
- dev_err(&pdev->dev, "failed to add fgu disable action\n");
+ dev_err(dev, "failed to add fgu disable action\n");
return ret;
}
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
- dev_err(&pdev->dev, "no irq resource specified\n");
+ dev_err(dev, "no irq resource specified\n");
return irq;
}
@@ -1046,17 +1047,17 @@ static int sc27xx_fgu_probe(struct platform_device *pdev)
irq = gpiod_to_irq(data->gpiod);
if (irq < 0) {
- dev_err(&pdev->dev, "failed to translate GPIO to IRQ\n");
+ dev_err(dev, "failed to translate GPIO to IRQ\n");
return irq;
}
- ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+ ret = devm_request_threaded_irq(dev, irq, NULL,
sc27xx_fgu_bat_detection,
IRQF_ONESHOT | IRQF_TRIGGER_RISING |
IRQF_TRIGGER_FALLING,
pdev->name, data);
if (ret) {
- dev_err(&pdev->dev, "failed to request IRQ\n");
+ dev_err(dev, "failed to request IRQ\n");
return ret;
}
--
2.11.0
^ permalink raw reply related
* Re: [RFC PATCH v2 0/5] sched/cpufreq: Make schedutil energy aware
From: Patrick Bellasi @ 2019-07-08 11:13 UTC (permalink / raw)
To: Douglas Raillard
Cc: Peter Zijlstra, linux-kernel, linux-pm, mingo, rjw, viresh.kumar,
quentin.perret, dietmar.eggemann
In-Reply-To: <590e3dd9-ea4e-5230-d12c-d04bb3916e89@arm.com>
On 03-Jul 14:38, Douglas Raillard wrote:
> Hi Peter,
>
> On 7/2/19 4:44 PM, Peter Zijlstra wrote:
> > On Thu, Jun 27, 2019 at 06:15:58PM +0100, Douglas RAILLARD wrote:
> > > Make schedutil cpufreq governor energy-aware.
> > >
> > > - patch 1 introduces a function to retrieve a frequency given a base
> > > frequency and an energy cost margin.
> > > - patch 2 links Energy Model perf_domain to sugov_policy.
> > > - patch 3 updates get_next_freq() to make use of the Energy Model.
> >
> > >
> > > 1) Selecting the highest possible frequency for a given cost. Some
> > > platforms can have lower frequencies that are less efficient than
> > > higher ones, in which case they should be skipped for most purposes.
> > > They can still be useful to give more freedom to thermal throttling
> > > mechanisms, but not under normal circumstances.
> > > note: the EM framework will warn about such OPPs "hertz/watts ratio
> > > non-monotonically decreasing"
> >
> > Humm, for some reason I was thinking we explicitly skipped those OPPs
> > and they already weren't used.
> >
> > This isn't in fact so, and these first few patches make it so?
>
> That's correct, the cost information about each OPP has been introduced recently in mainline
> by the energy model series. Without that info, the only way to skip them that comes to my
> mind is to set a policy min frequency, since these inefficient OPPs are usually located
> at the lower end.
Perhaps it's also worth to point out that the alternative approach you
point out above is a system wide solution.
While, the ramp_boost thingy you propose, it's a more fine grained
mechanisms which could be extended in the future to have a per-task
side. IOW, it could contribute to have better user-space hints, for
example to ramp_boost more certain tasks and not others.
Best,
Patrick
--
#include <best/regards.h>
Patrick Bellasi
^ permalink raw reply
* Re: [RFC PATCH v2 0/5] sched/cpufreq: Make schedutil energy aware
From: Patrick Bellasi @ 2019-07-08 11:09 UTC (permalink / raw)
To: Douglas Raillard
Cc: Peter Zijlstra, linux-kernel, linux-pm, mingo, rjw, viresh.kumar,
quentin.perret, dietmar.eggemann
In-Reply-To: <5198292b-1874-9ff4-6a9f-826a5ea00466@arm.com>
On 03-Jul 17:36, Douglas Raillard wrote:
> On 7/2/19 4:51 PM, Peter Zijlstra wrote:
> > On Thu, Jun 27, 2019 at 06:15:58PM +0100, Douglas RAILLARD wrote:
[...]
> > I'm not immediately seeing how it is transient; that is, PELT has a
> > wobble in it's steady state, is that accounted for?
> >
>
> The transient-ness of the ramp boost I'm introducing comes from the fact that for a
> periodic task at steady state, task_ue.enqueued <= task_u when the task is executing.
^^^^^^^^^^^^^^^
I find your above "at steady state" a bit confusing.
The condition "task_ue.enqueue <= task_u" is true only for the first
task's big activation after a series of small activations, e.g. a task
switching from 20% to 70%.
That's the transient stat you refer to, isn't it?
> That is because task_ue.enqueued is sampled at dequeue time, precisely at the moment
> at which task_u is reaching its max for that task.
Right, so in the example above we will have enqueued=20% while task_u
is going above to converge towards 70%
> Since we only take into account positive boosts, ramp boost will
> only have an impact in the "increase transients".
Right.
I think Peter was referring to the smallish wobbles we see when the
task already converged to 70%. If that's the case I would say they are
already fully covered also by the current util_est.
You are also correct in pointing out that in the steady state
ramp_boost will not be triggered in that steady state.
IMU, that's for two main reasons:
a) it's very likely that enqueued <= util_avg
b) even in case enqueued should turn out to be _slightly_ bigger then
util_avg, the corresponding (proportional) ramp_boost would be so
tiny to not have any noticeable effect on OPP selection.
Am I correct on point b) above?
Could you maybe come up with some experimental numbers related to that
case specifically?
Best,
Patrick
--
#include <best/regards.h>
Patrick Bellasi
^ permalink raw reply
* Re: [PATCH v11 1/5] sched/core: uclamp: Extend CPU's cgroup controller
From: Quentin Perret @ 2019-07-08 11:08 UTC (permalink / raw)
To: Patrick Bellasi
Cc: linux-kernel, linux-pm, Ingo Molnar, Peter Zijlstra, Tejun Heo,
Rafael J . Wysocki, Vincent Guittot, Viresh Kumar, Paul Turner,
Dietmar Eggemann, Morten Rasmussen, Juri Lelli, Todd Kjos,
Joel Fernandes, Steve Muckle, Suren Baghdasaryan, Alessio Balsini
In-Reply-To: <20190708084357.12944-2-patrick.bellasi@arm.com>
Hi Patrick,
On Monday 08 Jul 2019 at 09:43:53 (+0100), Patrick Bellasi wrote:
> +static inline int uclamp_scale_from_percent(char *buf, u64 *value)
> +{
> + *value = SCHED_CAPACITY_SCALE;
> +
> + buf = strim(buf);
> + if (strncmp("max", buf, 4)) {
> + s64 percent;
> + int ret;
> +
> + ret = cgroup_parse_float(buf, 2, &percent);
> + if (ret)
> + return ret;
> +
> + percent <<= SCHED_CAPACITY_SHIFT;
> + *value = DIV_ROUND_CLOSEST_ULL(percent, 10000);
> + }
> +
> + return 0;
> +}
> +
> +static inline u64 uclamp_percent_from_scale(u64 value)
> +{
> + return DIV_ROUND_CLOSEST_ULL(value * 10000, SCHED_CAPACITY_SCALE);
> +}
FWIW, I tried the patches and realized these conversions result in a
'funny' behaviour from a user's perspective. Things like this happen:
$ echo 20 > cpu.uclamp.min
$ cat cpu.uclamp.min
20.2
$ echo 20.2 > cpu.uclamp.min
$ cat cpu.uclamp.min
20.21
Having looked at the code, I get why this is happening, but I'm not sure
if a random user will. It's not an issue per se, but it's just a bit
weird.
I guess one way to fix this would be to revert back to having a
1024-scale for the cgroup interface too ... Though I understand Tejun
wanted % for consistency with other things.
So, I'm not sure if this is still up for discussion, but in any case I
wanted to say I support your original idea of using a 1024-scale for the
cgroups interface, since that would solve the 'issue' above and keeps
things consistent with the per-task API too.
Thanks,
Quentin
^ permalink raw reply
* Re: [PATCH] cpufreq: imx-cpufreq-dt: Assign max supported frequency as suspend frequency
From: Leonard Crestez @ 2019-07-08 11:04 UTC (permalink / raw)
To: Anson Huang, viresh.kumar@linaro.org
Cc: rjw@rjwysocki.net, shawnguo@kernel.org, s.hauer@pengutronix.de,
kernel@pengutronix.de, festevam@gmail.com,
linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, dl-linux-imx, Lucas Stach
In-Reply-To: <20190708074624.910-1-Anson.Huang@nxp.com>
On 7/8/2019 10:55 AM, Anson.Huang@nxp.com wrote:
> To reduce the suspend/resume latency, CPU's max supported frequency
> should be used during low level suspend/resume phase, "opp-suspend"
> property is NOT feasible since OPP defined in DT could be NOT supported
> according to speed garding and market segment fuse settings. So we
> can assign the cpufreq policy's suspend_freq with max available
> frequency provided by cpufreq driver.
>
> Signed-off-by: Anson Huang <Anson.Huang@nxp.com>
> diff --git a/drivers/cpufreq/imx-cpufreq-dt.c b/drivers/cpufreq/imx-cpufreq-dt.c
> +static int __init imx_cpufreq_dt_setup_suspend_opp(void)
> +{
> + struct cpufreq_policy *policy = cpufreq_cpu_get(0);
> +
> + policy->suspend_freq = cpufreq_quick_get_max(0);
> +
> + return 0;
> +}
> +late_initcall(imx_cpufreq_dt_setup_suspend_opp);
The imx-cpufreq-dt driver is built as a module by default and this patch
produces an error:
In file included from ../drivers/cpufreq/imx-cpufreq-dt.c:11:
../include/linux/module.h:131:42: error: redefinition of ‘__inittest’
static inline initcall_t __maybe_unused __inittest(void) \
^~~~~~~~~~
../include/linux/device.h:1656:1: note: in expansion of macro ‘module_init’
module_init(__driver##_init); \
^~~~~~~~~~~
As far as I can tell late_initcall is not supported for modules.
Viresh: "max freq as suspend freq" is something that could be useful for
other SOC families. The hardware can suspend at any freq; it's just that
the highest one makes sense because it makes suspend/resume slightly faster.
Could this behavior be pushed to cpufreq-dt as a bool flag inside struct
cpufreq_dt_platform_data?
Only a few other platforms use this, most others pass NULL like imx. But
passing custom SOC-specific flags to cpufreq-dt makes a lot of sense
--
Regards,
Leonard
^ permalink raw reply
* [PATCH V7 5/7] cpufreq: Register notifiers with the PM QoS framework
From: Viresh Kumar @ 2019-07-08 10:57 UTC (permalink / raw)
To: Rafael Wysocki
Cc: Viresh Kumar, linux-pm, Vincent Guittot, mka, ulf.hansson, sfr,
pavel, Rafael J . Wysocki, linux-kernel
In-Reply-To: <5ad2624194baa2f53acc1f1e627eb7684c577a19.1562210705.git.viresh.kumar@linaro.org>
This registers the notifiers for min/max frequency constraints with the
PM QoS framework. The constraints are also taken into consideration in
cpufreq_set_policy().
This also relocates cpufreq_policy_put_kobj() as it is required to be
called from cpufreq_policy_alloc() now.
refresh_frequency_limits() is updated to avoid calling
cpufreq_set_policy() for inactive policies and handle_update() is
updated to have proper locking in place.
No constraints are added until now though.
Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
V6->V7:
- All callers of refresh_frequency_limits(), except handle_update(),
take the policy->rwsem and result in deadlock as
refresh_frequency_limits() also takes the same lock again. Fix that
by taking the rwsem from handle_update() instead.
@Rafael: Sending it before Pavel has verified it as I would be offline
later, in case you want to apply this today itself.
drivers/cpufreq/cpufreq.c | 135 +++++++++++++++++++++++++++++---------
include/linux/cpufreq.h | 3 +
2 files changed, 108 insertions(+), 30 deletions(-)
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index ceb57af15ca0..b96ef6db1bfe 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -26,6 +26,7 @@
#include <linux/kernel_stat.h>
#include <linux/module.h>
#include <linux/mutex.h>
+#include <linux/pm_qos.h>
#include <linux/slab.h>
#include <linux/suspend.h>
#include <linux/syscore_ops.h>
@@ -999,7 +1000,7 @@ static void add_cpu_dev_symlink(struct cpufreq_policy *policy, unsigned int cpu)
{
struct device *dev = get_cpu_device(cpu);
- if (!dev)
+ if (unlikely(!dev))
return;
if (cpumask_test_and_set_cpu(cpu, policy->real_cpus))
@@ -1117,14 +1118,16 @@ static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy, unsigned int cp
static void refresh_frequency_limits(struct cpufreq_policy *policy)
{
- struct cpufreq_policy new_policy = *policy;
-
- pr_debug("updating policy for CPU %u\n", policy->cpu);
+ struct cpufreq_policy new_policy;
- new_policy.min = policy->user_policy.min;
- new_policy.max = policy->user_policy.max;
+ if (!policy_is_inactive(policy)) {
+ new_policy = *policy;
+ pr_debug("updating policy for CPU %u\n", policy->cpu);
- cpufreq_set_policy(policy, &new_policy);
+ new_policy.min = policy->user_policy.min;
+ new_policy.max = policy->user_policy.max;
+ cpufreq_set_policy(policy, &new_policy);
+ }
}
static void handle_update(struct work_struct *work)
@@ -1133,14 +1136,60 @@ static void handle_update(struct work_struct *work)
container_of(work, struct cpufreq_policy, update);
pr_debug("handle_update for cpu %u called\n", policy->cpu);
+ down_write(&policy->rwsem);
refresh_frequency_limits(policy);
+ up_write(&policy->rwsem);
+}
+
+static int cpufreq_notifier_min(struct notifier_block *nb, unsigned long freq,
+ void *data)
+{
+ struct cpufreq_policy *policy = container_of(nb, struct cpufreq_policy, nb_min);
+
+ schedule_work(&policy->update);
+ return 0;
+}
+
+static int cpufreq_notifier_max(struct notifier_block *nb, unsigned long freq,
+ void *data)
+{
+ struct cpufreq_policy *policy = container_of(nb, struct cpufreq_policy, nb_max);
+
+ schedule_work(&policy->update);
+ return 0;
+}
+
+static void cpufreq_policy_put_kobj(struct cpufreq_policy *policy)
+{
+ struct kobject *kobj;
+ struct completion *cmp;
+
+ down_write(&policy->rwsem);
+ cpufreq_stats_free_table(policy);
+ kobj = &policy->kobj;
+ cmp = &policy->kobj_unregister;
+ up_write(&policy->rwsem);
+ kobject_put(kobj);
+
+ /*
+ * We need to make sure that the underlying kobj is
+ * actually not referenced anymore by anybody before we
+ * proceed with unloading.
+ */
+ pr_debug("waiting for dropping of refcount\n");
+ wait_for_completion(cmp);
+ pr_debug("wait complete\n");
}
static struct cpufreq_policy *cpufreq_policy_alloc(unsigned int cpu)
{
struct cpufreq_policy *policy;
+ struct device *dev = get_cpu_device(cpu);
int ret;
+ if (!dev)
+ return NULL;
+
policy = kzalloc(sizeof(*policy), GFP_KERNEL);
if (!policy)
return NULL;
@@ -1157,7 +1206,7 @@ static struct cpufreq_policy *cpufreq_policy_alloc(unsigned int cpu)
ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq,
cpufreq_global_kobject, "policy%u", cpu);
if (ret) {
- pr_err("%s: failed to init policy->kobj: %d\n", __func__, ret);
+ dev_err(dev, "%s: failed to init policy->kobj: %d\n", __func__, ret);
/*
* The entire policy object will be freed below, but the extra
* memory allocated for the kobject name needs to be freed by
@@ -1167,6 +1216,25 @@ static struct cpufreq_policy *cpufreq_policy_alloc(unsigned int cpu)
goto err_free_real_cpus;
}
+ policy->nb_min.notifier_call = cpufreq_notifier_min;
+ policy->nb_max.notifier_call = cpufreq_notifier_max;
+
+ ret = dev_pm_qos_add_notifier(dev, &policy->nb_min,
+ DEV_PM_QOS_MIN_FREQUENCY);
+ if (ret) {
+ dev_err(dev, "Failed to register MIN QoS notifier: %d (%*pbl)\n",
+ ret, cpumask_pr_args(policy->cpus));
+ goto err_kobj_remove;
+ }
+
+ ret = dev_pm_qos_add_notifier(dev, &policy->nb_max,
+ DEV_PM_QOS_MAX_FREQUENCY);
+ if (ret) {
+ dev_err(dev, "Failed to register MAX QoS notifier: %d (%*pbl)\n",
+ ret, cpumask_pr_args(policy->cpus));
+ goto err_min_qos_notifier;
+ }
+
INIT_LIST_HEAD(&policy->policy_list);
init_rwsem(&policy->rwsem);
spin_lock_init(&policy->transition_lock);
@@ -1177,6 +1245,11 @@ static struct cpufreq_policy *cpufreq_policy_alloc(unsigned int cpu)
policy->cpu = cpu;
return policy;
+err_min_qos_notifier:
+ dev_pm_qos_remove_notifier(dev, &policy->nb_min,
+ DEV_PM_QOS_MIN_FREQUENCY);
+err_kobj_remove:
+ cpufreq_policy_put_kobj(policy);
err_free_real_cpus:
free_cpumask_var(policy->real_cpus);
err_free_rcpumask:
@@ -1189,30 +1262,9 @@ static struct cpufreq_policy *cpufreq_policy_alloc(unsigned int cpu)
return NULL;
}
-static void cpufreq_policy_put_kobj(struct cpufreq_policy *policy)
-{
- struct kobject *kobj;
- struct completion *cmp;
-
- down_write(&policy->rwsem);
- cpufreq_stats_free_table(policy);
- kobj = &policy->kobj;
- cmp = &policy->kobj_unregister;
- up_write(&policy->rwsem);
- kobject_put(kobj);
-
- /*
- * We need to make sure that the underlying kobj is
- * actually not referenced anymore by anybody before we
- * proceed with unloading.
- */
- pr_debug("waiting for dropping of refcount\n");
- wait_for_completion(cmp);
- pr_debug("wait complete\n");
-}
-
static void cpufreq_policy_free(struct cpufreq_policy *policy)
{
+ struct device *dev = get_cpu_device(policy->cpu);
unsigned long flags;
int cpu;
@@ -1224,6 +1276,11 @@ static void cpufreq_policy_free(struct cpufreq_policy *policy)
per_cpu(cpufreq_cpu_data, cpu) = NULL;
write_unlock_irqrestore(&cpufreq_driver_lock, flags);
+ dev_pm_qos_remove_notifier(dev, &policy->nb_max,
+ DEV_PM_QOS_MAX_FREQUENCY);
+ dev_pm_qos_remove_notifier(dev, &policy->nb_min,
+ DEV_PM_QOS_MIN_FREQUENCY);
+
cpufreq_policy_put_kobj(policy);
free_cpumask_var(policy->real_cpus);
free_cpumask_var(policy->related_cpus);
@@ -2283,6 +2340,8 @@ int cpufreq_set_policy(struct cpufreq_policy *policy,
struct cpufreq_policy *new_policy)
{
struct cpufreq_governor *old_gov;
+ struct device *cpu_dev = get_cpu_device(policy->cpu);
+ unsigned long min, max;
int ret;
pr_debug("setting new policy for CPU %u: %u - %u kHz\n",
@@ -2297,11 +2356,27 @@ int cpufreq_set_policy(struct cpufreq_policy *policy,
if (new_policy->min > new_policy->max)
return -EINVAL;
+ /*
+ * PM QoS framework collects all the requests from users and provide us
+ * the final aggregated value here.
+ */
+ min = dev_pm_qos_read_value(cpu_dev, DEV_PM_QOS_MIN_FREQUENCY);
+ max = dev_pm_qos_read_value(cpu_dev, DEV_PM_QOS_MAX_FREQUENCY);
+
+ if (min > new_policy->min)
+ new_policy->min = min;
+ if (max < new_policy->max)
+ new_policy->max = max;
+
/* verify the cpu speed can be set within this limit */
ret = cpufreq_driver->verify(new_policy);
if (ret)
return ret;
+ /*
+ * The notifier-chain shall be removed once all the users of
+ * CPUFREQ_ADJUST are moved to use the QoS framework.
+ */
/* adjust if necessary - all reasons */
blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
CPUFREQ_ADJUST, new_policy);
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index a1467aa7f58b..95425941f46d 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -147,6 +147,9 @@ struct cpufreq_policy {
/* Pointer to the cooling device if used for thermal mitigation */
struct thermal_cooling_device *cdev;
+
+ struct notifier_block nb_min;
+ struct notifier_block nb_max;
};
struct cpufreq_freqs {
--
2.21.0.rc0.269.g1a574e7a288b
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox