mirror of
https://github.com/torvalds/linux.git
synced 2026-06-10 23:53:52 +02:00
-----BEGIN PGP SIGNATURE-----
iQIzBAABCAAdFiEEZH8oZUiU471FcZm+ONu9yGCSaT4FAmFBpvcACgkQONu9yGCS
aT7JVxAAof4h5rPObKwhFBu4qOHXEtlHrFAF1xTEaQZnIbv9CkEF0LPufWXP+nKS
mQDOdDmX3rZhWXZbnNK3ZxBADJXyHS6M0jHByuGrzQ8dmMONJtpjYUjxou6k/xg2
4ECHqzeVbwbWuKrJrAfC1xuZofIHXZBHrkAQmLoMw8ERp309lgPS2cXDOXRzn/n/
ri+5AhTaw1ZG1JXrXvyfoxjbdE/eEeJXx8N/zJf0sas5lYpsqeAWTgXBkNpPeJm7
G66ISwEVp6TPxihpRSKwUhADjuM2+EAok2WXwwTvO0s00vE7LL5ijK27hhP5ual1
+xtxBHag95oIZ+sq1t3z4BgmE1n3z/lHkQki98JQaWShABLGhMdKYPF75hMzR6Pw
j0TvLHdkPRSrtUelc7rGtqaT9tF9+RU59I5fPGlBpGckOJ5u2IHCKdjk1WadRgrj
JF7R8ApfP18y1X46tDfr/CIPIZfTVNJyd7hZ1zt11wdBYFmaw/oNyg81OalqzaWf
ckUIt6AucRQ04uuFfhSaTuxLSEl5Uuh6W30HuO/0N3CoDsfD1RMc+76sXORt/JdK
MPxTy124KM6VZADVW4tQXHMoGkLftqTAIgRKt4iRPz80rdhACJFoZJlmVON0MmKV
tSODsqGBxIxhkLj197vQzT152G4wBkmzPtqJfJH7lkGKmBpoKZE=
=lJCV
-----END PGP SIGNATURE-----
Merge 5.10.65 into android12-5.10-lts
Changes in 5.10.65
locking/mutex: Fix HANDOFF condition
regmap: fix the offset of register error log
regulator: tps65910: Silence deferred probe error
crypto: mxs-dcp - Check for DMA mapping errors
sched/deadline: Fix reset_on_fork reporting of DL tasks
power: supply: axp288_fuel_gauge: Report register-address on readb / writeb errors
crypto: omap-sham - clear dma flags only after omap_sham_update_dma_stop()
sched/deadline: Fix missing clock update in migrate_task_rq_dl()
rcu/tree: Handle VM stoppage in stall detection
EDAC/mce_amd: Do not load edac_mce_amd module on guests
posix-cpu-timers: Force next expiration recalc after itimer reset
hrtimer: Avoid double reprogramming in __hrtimer_start_range_ns()
hrtimer: Ensure timerfd notification for HIGHRES=n
udf: Check LVID earlier
udf: Fix iocharset=utf8 mount option
isofs: joliet: Fix iocharset=utf8 mount option
bcache: add proper error unwinding in bcache_device_init
blk-throtl: optimize IOPS throttle for large IO scenarios
nvme-tcp: don't update queue count when failing to set io queues
nvme-rdma: don't update queue count when failing to set io queues
nvmet: pass back cntlid on successful completion
power: supply: smb347-charger: Add missing pin control activation
power: supply: max17042_battery: fix typo in MAx17042_TOFF
s390/cio: add dev_busid sysfs entry for each subchannel
s390/zcrypt: fix wrong offset index for APKA master key valid state
libata: fix ata_host_start()
crypto: omap - Fix inconsistent locking of device lists
crypto: qat - do not ignore errors from enable_vf2pf_comms()
crypto: qat - handle both source of interrupt in VF ISR
crypto: qat - fix reuse of completion variable
crypto: qat - fix naming for init/shutdown VF to PF notifications
crypto: qat - do not export adf_iov_putmsg()
fcntl: fix potential deadlock for &fasync_struct.fa_lock
udf_get_extendedattr() had no boundary checks.
s390/kasan: fix large PMD pages address alignment check
s390/pci: fix misleading rc in clp_set_pci_fn()
s390/debug: keep debug data on resize
s390/debug: fix debug area life cycle
s390/ap: fix state machine hang after failure to enable irq
power: supply: cw2015: use dev_err_probe to allow deferred probe
m68k: emu: Fix invalid free in nfeth_cleanup()
sched/numa: Fix is_core_idle()
sched: Fix UCLAMP_FLAG_IDLE setting
rcu: Fix to include first blocked task in stall warning
rcu: Add lockdep_assert_irqs_disabled() to rcu_sched_clock_irq() and callees
rcu: Fix stall-warning deadlock due to non-release of rcu_node ->lock
m68k: Fix invalid RMW_INSNS on CPUs that lack CAS
block: return ELEVATOR_DISCARD_MERGE if possible
spi: spi-fsl-dspi: Fix issue with uninitialized dma_slave_config
spi: spi-pic32: Fix issue with uninitialized dma_slave_config
genirq/timings: Fix error return code in irq_timings_test_irqs()
irqchip/loongson-pch-pic: Improve edge triggered interrupt support
lib/mpi: use kcalloc in mpi_resize
clocksource/drivers/sh_cmt: Fix wrong setting if don't request IRQ for clock source channel
block: nbd: add sanity check for first_minor
spi: coldfire-qspi: Use clk_disable_unprepare in the remove function
irqchip/gic-v3: Fix priority comparison when non-secure priorities are used
crypto: qat - use proper type for vf_mask
certs: Trigger creation of RSA module signing key if it's not an RSA key
tpm: ibmvtpm: Avoid error message when process gets signal while waiting
x86/mce: Defer processing of early errors
spi: davinci: invoke chipselect callback
blk-crypto: fix check for too-large dun_bytes
regulator: vctrl: Use locked regulator_get_voltage in probe path
regulator: vctrl: Avoid lockdep warning in enable/disable ops
spi: sprd: Fix the wrong WDG_LOAD_VAL
spi: spi-zynq-qspi: use wait_for_completion_timeout to make zynq_qspi_exec_mem_op not interruptible
EDAC/i10nm: Fix NVDIMM detection
drm/panfrost: Fix missing clk_disable_unprepare() on error in panfrost_clk_init()
drm/gma500: Fix end of loop tests for list_for_each_entry
ASoC: mediatek: mt8183: Fix Unbalanced pm_runtime_enable in mt8183_afe_pcm_dev_probe
media: TDA1997x: enable EDID support
leds: is31fl32xx: Fix missing error code in is31fl32xx_parse_dt()
soc: rockchip: ROCKCHIP_GRF should not default to y, unconditionally
media: cxd2880-spi: Fix an error handling path
drm/of: free the right object
bpf: Fix a typo of reuseport map in bpf.h.
bpf: Fix potential memleak and UAF in the verifier.
drm/of: free the iterator object on failure
gve: fix the wrong AdminQ buffer overflow check
libbpf: Fix the possible memory leak on error
ARM: dts: aspeed-g6: Fix HVI3C function-group in pinctrl dtsi
arm64: dts: renesas: r8a77995: draak: Remove bogus adv7511w properties
i40e: improve locking of mac_filter_hash
soc: qcom: rpmhpd: Use corner in power_off
libbpf: Fix removal of inner map in bpf_object__create_map
gfs2: Fix memory leak of object lsi on error return path
firmware: fix theoretical UAF race with firmware cache and resume
driver core: Fix error return code in really_probe()
ionic: cleanly release devlink instance
media: dvb-usb: fix uninit-value in dvb_usb_adapter_dvb_init
media: dvb-usb: fix uninit-value in vp702x_read_mac_addr
media: dvb-usb: Fix error handling in dvb_usb_i2c_init
media: go7007: fix memory leak in go7007_usb_probe
media: go7007: remove redundant initialization
media: rockchip/rga: use pm_runtime_resume_and_get()
media: rockchip/rga: fix error handling in probe
media: coda: fix frame_mem_ctrl for YUV420 and YVU420 formats
media: atomisp: fix the uninitialized use and rename "retvalue"
Bluetooth: sco: prevent information leak in sco_conn_defer_accept()
6lowpan: iphc: Fix an off-by-one check of array index
drm/amdgpu/acp: Make PM domain really work
tcp: seq_file: Avoid skipping sk during tcp_seek_last_pos
ARM: dts: meson8: Use a higher default GPU clock frequency
ARM: dts: meson8b: odroidc1: Fix the pwm regulator supply properties
ARM: dts: meson8b: mxq: Fix the pwm regulator supply properties
ARM: dts: meson8b: ec100: Fix the pwm regulator supply properties
net/mlx5e: Prohibit inner indir TIRs in IPoIB
net/mlx5e: Block LRO if firmware asks for tunneled LRO
cgroup/cpuset: Fix a partition bug with hotplug
drm: mxsfb: Enable recovery on underflow
drm: mxsfb: Increase number of outstanding requests on V4 and newer HW
drm: mxsfb: Clear FIFO_CLEAR bit
net: cipso: fix warnings in netlbl_cipsov4_add_std
Bluetooth: mgmt: Fix wrong opcode in the response for add_adv cmd
arm64: dts: renesas: rzg2: Convert EtherAVB to explicit delay handling
arm64: dts: renesas: hihope-rzg2-ex: Add EtherAVB internal rx delay
devlink: Break parameter notification sequence to be before/after unload/load driver
net/mlx5: Fix missing return value in mlx5_devlink_eswitch_inline_mode_set()
i2c: highlander: add IRQ check
leds: lt3593: Put fwnode in any case during ->probe()
leds: trigger: audio: Add an activate callback to ensure the initial brightness is set
media: em28xx-input: fix refcount bug in em28xx_usb_disconnect
media: venus: venc: Fix potential null pointer dereference on pointer fmt
PCI: PM: Avoid forcing PCI_D0 for wakeup reasons inconsistently
PCI: PM: Enable PME if it can be signaled from D3cold
bpf, samples: Add missing mprog-disable to xdp_redirect_cpu's optstring
soc: qcom: smsm: Fix missed interrupts if state changes while masked
debugfs: Return error during {full/open}_proxy_open() on rmmod
Bluetooth: increase BTNAMSIZ to 21 chars to fix potential buffer overflow
PM: EM: Increase energy calculation precision
selftests/bpf: Fix bpf-iter-tcp4 test to print correctly the dest IP
drm/msm/mdp4: refactor HW revision detection into read_mdp_hw_revision
drm/msm/mdp4: move HW revision detection to earlier phase
drm/msm/dpu: make dpu_hw_ctl_clear_all_blendstages clear necessary LMs
arm64: dts: exynos: correct GIC CPU interfaces address range on Exynos7
counter: 104-quad-8: Return error when invalid mode during ceiling_write
cgroup/cpuset: Miscellaneous code cleanup
cgroup/cpuset: Fix violation of cpuset locking rule
ASoC: Intel: Fix platform ID matching
Bluetooth: fix repeated calls to sco_sock_kill
drm/msm/dsi: Fix some reference counted resource leaks
net/mlx5: Register to devlink ingress VLAN filter trap
net/mlx5: Fix unpublish devlink parameters
ASoC: rt5682: Implement remove callback
ASoC: rt5682: Properly turn off regulators if wrong device ID
usb: dwc3: meson-g12a: add IRQ check
usb: dwc3: qcom: add IRQ check
usb: gadget: udc: at91: add IRQ check
usb: gadget: udc: s3c2410: add IRQ check
usb: phy: fsl-usb: add IRQ check
usb: phy: twl6030: add IRQ checks
usb: gadget: udc: renesas_usb3: Fix soc_device_match() abuse
selftests/bpf: Fix test_core_autosize on big-endian machines
devlink: Clear whole devlink_flash_notify struct
samples: pktgen: add missing IPv6 option to pktgen scripts
Bluetooth: Move shutdown callback before flushing tx and rx queue
PM: cpu: Make notifier chain use a raw_spinlock_t
usb: host: ohci-tmio: add IRQ check
usb: phy: tahvo: add IRQ check
libbpf: Re-build libbpf.so when libbpf.map changes
mac80211: Fix insufficient headroom issue for AMSDU
locking/lockdep: Mark local_lock_t
locking/local_lock: Add missing owner initialization
lockd: Fix invalid lockowner cast after vfs_test_lock
nfsd4: Fix forced-expiry locking
arm64: dts: marvell: armada-37xx: Extend PCIe MEM space
clk: staging: correct reference to config IOMEM to config HAS_IOMEM
i2c: synquacer: fix deferred probing
firmware: raspberrypi: Keep count of all consumers
firmware: raspberrypi: Fix a leak in 'rpi_firmware_get()'
usb: gadget: mv_u3d: request_irq() after initializing UDC
mm/swap: consider max pages in iomap_swapfile_add_extent
lkdtm: replace SCSI_DISPATCH_CMD with SCSI_QUEUE_RQ
Bluetooth: add timeout sanity check to hci_inquiry
i2c: iop3xx: fix deferred probing
i2c: s3c2410: fix IRQ check
i2c: fix platform_get_irq.cocci warnings
i2c: hix5hd2: fix IRQ check
gfs2: init system threads before freeze lock
rsi: fix error code in rsi_load_9116_firmware()
rsi: fix an error code in rsi_probe()
ASoC: Intel: kbl_da7219_max98927: Fix format selection for max98373
ASoC: Intel: Skylake: Leave data as is when invoking TLV IPCs
ASoC: Intel: Skylake: Fix module resource and format selection
mmc: sdhci: Fix issue with uninitialized dma_slave_config
mmc: dw_mmc: Fix issue with uninitialized dma_slave_config
mmc: moxart: Fix issue with uninitialized dma_slave_config
bpf: Fix possible out of bound write in narrow load handling
CIFS: Fix a potencially linear read overflow
i2c: mt65xx: fix IRQ check
i2c: xlp9xx: fix main IRQ check
usb: ehci-orion: Handle errors of clk_prepare_enable() in probe
usb: bdc: Fix an error handling path in 'bdc_probe()' when no suitable DMA config is available
usb: bdc: Fix a resource leak in the error handling path of 'bdc_probe()'
tty: serial: fsl_lpuart: fix the wrong mapbase value
ASoC: wcd9335: Fix a double irq free in the remove function
ASoC: wcd9335: Fix a memory leak in the error handling path of the probe function
ASoC: wcd9335: Disable irq on slave ports in the remove function
iwlwifi: follow the new inclusive terminology
iwlwifi: skip first element in the WTAS ACPI table
ice: Only lock to update netdev dev_addr
ath6kl: wmi: fix an error code in ath6kl_wmi_sync_point()
atlantic: Fix driver resume flow.
bcma: Fix memory leak for internally-handled cores
brcmfmac: pcie: fix oops on failure to resume and reprobe
ipv6: make exception cache less predictible
ipv4: make exception cache less predictible
net: sched: Fix qdisc_rate_table refcount leak when get tcf_block failed
net: qualcomm: fix QCA7000 checksum handling
octeontx2-af: Fix loop in free and unmap counter
octeontx2-af: Fix static code analyzer reported issues
octeontx2-af: Set proper errorcode for IPv4 checksum errors
ipv4: fix endianness issue in inet_rtm_getroute_build_skb()
ASoC: rt5682: Remove unused variable in rt5682_i2c_remove()
iwlwifi Add support for ax201 in Samsung Galaxy Book Flex2 Alpha
f2fs: guarantee to write dirty data when enabling checkpoint back
time: Handle negative seconds correctly in timespec64_to_ns()
io_uring: IORING_OP_WRITE needs hash_reg_file set
bio: fix page leak bio_add_hw_page failure
tty: Fix data race between tiocsti() and flush_to_ldisc()
perf/x86/amd/ibs: Extend PERF_PMU_CAP_NO_EXCLUDE to IBS Op
x86/resctrl: Fix a maybe-uninitialized build warning treated as error
Revert "KVM: x86: mmu: Add guest physical address check in translate_gpa()"
KVM: s390: index kvm->arch.idle_mask by vcpu_idx
KVM: x86: Update vCPU's hv_clock before back to guest when tsc_offset is adjusted
KVM: VMX: avoid running vmx_handle_exit_irqoff in case of emulation
KVM: nVMX: Unconditionally clear nested.pi_pending on nested VM-Enter
ARM: dts: at91: add pinctrl-{names, 0} for all gpios
fuse: truncate pagecache on atomic_o_trunc
fuse: flush extending writes
IMA: remove -Wmissing-prototypes warning
IMA: remove the dependency on CRYPTO_MD5
fbmem: don't allow too huge resolutions
backlight: pwm_bl: Improve bootloader/kernel device handover
clk: kirkwood: Fix a clocking boot regression
Linux 5.10.65
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Change-Id: Ie0b9306ba6ee4193de3200df7cdacaeba152b83e
377 lines
9.1 KiB
C
377 lines
9.1 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Energy Model of devices
|
|
*
|
|
* Copyright (c) 2018-2020, Arm ltd.
|
|
* Written by: Quentin Perret, Arm ltd.
|
|
* Improvements provided by: Lukasz Luba, Arm ltd.
|
|
*/
|
|
|
|
#define pr_fmt(fmt) "energy_model: " fmt
|
|
|
|
#include <linux/cpu.h>
|
|
#include <linux/cpumask.h>
|
|
#include <linux/debugfs.h>
|
|
#include <linux/energy_model.h>
|
|
#include <linux/sched/topology.h>
|
|
#include <linux/slab.h>
|
|
|
|
/*
|
|
* Mutex serializing the registrations of performance domains and letting
|
|
* callbacks defined by drivers sleep.
|
|
*/
|
|
static DEFINE_MUTEX(em_pd_mutex);
|
|
|
|
static bool _is_cpu_device(struct device *dev)
|
|
{
|
|
return (dev->bus == &cpu_subsys);
|
|
}
|
|
|
|
#ifdef CONFIG_DEBUG_FS
|
|
static struct dentry *rootdir;
|
|
|
|
static void em_debug_create_ps(struct em_perf_state *ps, struct dentry *pd)
|
|
{
|
|
struct dentry *d;
|
|
char name[24];
|
|
|
|
snprintf(name, sizeof(name), "ps:%lu", ps->frequency);
|
|
|
|
/* Create per-ps directory */
|
|
d = debugfs_create_dir(name, pd);
|
|
debugfs_create_ulong("frequency", 0444, d, &ps->frequency);
|
|
debugfs_create_ulong("power", 0444, d, &ps->power);
|
|
debugfs_create_ulong("cost", 0444, d, &ps->cost);
|
|
}
|
|
|
|
static int em_debug_cpus_show(struct seq_file *s, void *unused)
|
|
{
|
|
seq_printf(s, "%*pbl\n", cpumask_pr_args(to_cpumask(s->private)));
|
|
|
|
return 0;
|
|
}
|
|
DEFINE_SHOW_ATTRIBUTE(em_debug_cpus);
|
|
|
|
static int em_debug_units_show(struct seq_file *s, void *unused)
|
|
{
|
|
struct em_perf_domain *pd = s->private;
|
|
char *units = pd->milliwatts ? "milliWatts" : "bogoWatts";
|
|
|
|
seq_printf(s, "%s\n", units);
|
|
|
|
return 0;
|
|
}
|
|
DEFINE_SHOW_ATTRIBUTE(em_debug_units);
|
|
|
|
static void em_debug_create_pd(struct device *dev)
|
|
{
|
|
struct dentry *d;
|
|
int i;
|
|
|
|
/* Create the directory of the performance domain */
|
|
d = debugfs_create_dir(dev_name(dev), rootdir);
|
|
|
|
if (_is_cpu_device(dev))
|
|
debugfs_create_file("cpus", 0444, d, dev->em_pd->cpus,
|
|
&em_debug_cpus_fops);
|
|
|
|
debugfs_create_file("units", 0444, d, dev->em_pd, &em_debug_units_fops);
|
|
|
|
/* Create a sub-directory for each performance state */
|
|
for (i = 0; i < dev->em_pd->nr_perf_states; i++)
|
|
em_debug_create_ps(&dev->em_pd->table[i], d);
|
|
|
|
}
|
|
|
|
static void em_debug_remove_pd(struct device *dev)
|
|
{
|
|
struct dentry *debug_dir;
|
|
|
|
debug_dir = debugfs_lookup(dev_name(dev), rootdir);
|
|
debugfs_remove_recursive(debug_dir);
|
|
}
|
|
|
|
static int __init em_debug_init(void)
|
|
{
|
|
/* Create /sys/kernel/debug/energy_model directory */
|
|
rootdir = debugfs_create_dir("energy_model", NULL);
|
|
|
|
return 0;
|
|
}
|
|
fs_initcall(em_debug_init);
|
|
#else /* CONFIG_DEBUG_FS */
|
|
static void em_debug_create_pd(struct device *dev) {}
|
|
static void em_debug_remove_pd(struct device *dev) {}
|
|
#endif
|
|
|
|
static int em_create_perf_table(struct device *dev, struct em_perf_domain *pd,
|
|
int nr_states, struct em_data_callback *cb)
|
|
{
|
|
unsigned long opp_eff, prev_opp_eff = ULONG_MAX;
|
|
unsigned long power, freq, prev_freq = 0;
|
|
struct em_perf_state *table;
|
|
int i, ret;
|
|
u64 fmax;
|
|
|
|
table = kcalloc(nr_states, sizeof(*table), GFP_KERNEL);
|
|
if (!table)
|
|
return -ENOMEM;
|
|
|
|
/* Build the list of performance states for this performance domain */
|
|
for (i = 0, freq = 0; i < nr_states; i++, freq++) {
|
|
/*
|
|
* active_power() is a driver callback which ceils 'freq' to
|
|
* lowest performance state of 'dev' above 'freq' and updates
|
|
* 'power' and 'freq' accordingly.
|
|
*/
|
|
ret = cb->active_power(&power, &freq, dev);
|
|
if (ret) {
|
|
dev_err(dev, "EM: invalid perf. state: %d\n",
|
|
ret);
|
|
goto free_ps_table;
|
|
}
|
|
|
|
/*
|
|
* We expect the driver callback to increase the frequency for
|
|
* higher performance states.
|
|
*/
|
|
if (freq <= prev_freq) {
|
|
dev_err(dev, "EM: non-increasing freq: %lu\n",
|
|
freq);
|
|
goto free_ps_table;
|
|
}
|
|
|
|
/*
|
|
* The power returned by active_state() is expected to be
|
|
* positive, in milli-watts and to fit into 16 bits.
|
|
*/
|
|
if (!power || power > EM_MAX_POWER) {
|
|
dev_err(dev, "EM: invalid power: %lu\n",
|
|
power);
|
|
goto free_ps_table;
|
|
}
|
|
|
|
table[i].power = power;
|
|
table[i].frequency = prev_freq = freq;
|
|
|
|
/*
|
|
* The hertz/watts efficiency ratio should decrease as the
|
|
* frequency grows on sane platforms. But this isn't always
|
|
* true in practice so warn the user if a higher OPP is more
|
|
* power efficient than a lower one.
|
|
*/
|
|
opp_eff = freq / power;
|
|
if (opp_eff >= prev_opp_eff)
|
|
dev_dbg(dev, "EM: hertz/watts ratio non-monotonically decreasing: em_perf_state %d >= em_perf_state%d\n",
|
|
i, i - 1);
|
|
prev_opp_eff = opp_eff;
|
|
}
|
|
|
|
/* Compute the cost of each performance state. */
|
|
fmax = (u64) table[nr_states - 1].frequency;
|
|
for (i = 0; i < nr_states; i++) {
|
|
unsigned long power_res = em_scale_power(table[i].power);
|
|
|
|
table[i].cost = div64_u64(fmax * power_res,
|
|
table[i].frequency);
|
|
}
|
|
|
|
pd->table = table;
|
|
pd->nr_perf_states = nr_states;
|
|
|
|
return 0;
|
|
|
|
free_ps_table:
|
|
kfree(table);
|
|
return -EINVAL;
|
|
}
|
|
|
|
static int em_create_pd(struct device *dev, int nr_states,
|
|
struct em_data_callback *cb, cpumask_t *cpus)
|
|
{
|
|
struct em_perf_domain *pd;
|
|
struct device *cpu_dev;
|
|
int cpu, ret;
|
|
|
|
if (_is_cpu_device(dev)) {
|
|
pd = kzalloc(sizeof(*pd) + cpumask_size(), GFP_KERNEL);
|
|
if (!pd)
|
|
return -ENOMEM;
|
|
|
|
cpumask_copy(em_span_cpus(pd), cpus);
|
|
} else {
|
|
pd = kzalloc(sizeof(*pd), GFP_KERNEL);
|
|
if (!pd)
|
|
return -ENOMEM;
|
|
}
|
|
|
|
ret = em_create_perf_table(dev, pd, nr_states, cb);
|
|
if (ret) {
|
|
kfree(pd);
|
|
return ret;
|
|
}
|
|
|
|
if (_is_cpu_device(dev))
|
|
for_each_cpu(cpu, cpus) {
|
|
cpu_dev = get_cpu_device(cpu);
|
|
cpu_dev->em_pd = pd;
|
|
}
|
|
|
|
dev->em_pd = pd;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* em_pd_get() - Return the performance domain for a device
|
|
* @dev : Device to find the performance domain for
|
|
*
|
|
* Returns the performance domain to which @dev belongs, or NULL if it doesn't
|
|
* exist.
|
|
*/
|
|
struct em_perf_domain *em_pd_get(struct device *dev)
|
|
{
|
|
if (IS_ERR_OR_NULL(dev))
|
|
return NULL;
|
|
|
|
return dev->em_pd;
|
|
}
|
|
EXPORT_SYMBOL_GPL(em_pd_get);
|
|
|
|
/**
|
|
* em_cpu_get() - Return the performance domain for a CPU
|
|
* @cpu : CPU to find the performance domain for
|
|
*
|
|
* Returns the performance domain to which @cpu belongs, or NULL if it doesn't
|
|
* exist.
|
|
*/
|
|
struct em_perf_domain *em_cpu_get(int cpu)
|
|
{
|
|
struct device *cpu_dev;
|
|
|
|
cpu_dev = get_cpu_device(cpu);
|
|
if (!cpu_dev)
|
|
return NULL;
|
|
|
|
return em_pd_get(cpu_dev);
|
|
}
|
|
EXPORT_SYMBOL_GPL(em_cpu_get);
|
|
|
|
/**
|
|
* em_dev_register_perf_domain() - Register the Energy Model (EM) for a device
|
|
* @dev : Device for which the EM is to register
|
|
* @nr_states : Number of performance states to register
|
|
* @cb : Callback functions providing the data of the Energy Model
|
|
* @cpus : Pointer to cpumask_t, which in case of a CPU device is
|
|
* obligatory. It can be taken from i.e. 'policy->cpus'. For other
|
|
* type of devices this should be set to NULL.
|
|
* @milliwatts : Flag indicating that the power values are in milliWatts or
|
|
* in some other scale. It must be set properly.
|
|
*
|
|
* Create Energy Model tables for a performance domain using the callbacks
|
|
* defined in cb.
|
|
*
|
|
* The @milliwatts is important to set with correct value. Some kernel
|
|
* sub-systems might rely on this flag and check if all devices in the EM are
|
|
* using the same scale.
|
|
*
|
|
* If multiple clients register the same performance domain, all but the first
|
|
* registration will be ignored.
|
|
*
|
|
* Return 0 on success
|
|
*/
|
|
int em_dev_register_perf_domain(struct device *dev, unsigned int nr_states,
|
|
struct em_data_callback *cb, cpumask_t *cpus,
|
|
bool milliwatts)
|
|
{
|
|
unsigned long cap, prev_cap = 0;
|
|
int cpu, ret;
|
|
|
|
if (!dev || !nr_states || !cb)
|
|
return -EINVAL;
|
|
|
|
/*
|
|
* Use a mutex to serialize the registration of performance domains and
|
|
* let the driver-defined callback functions sleep.
|
|
*/
|
|
mutex_lock(&em_pd_mutex);
|
|
|
|
if (dev->em_pd) {
|
|
ret = -EEXIST;
|
|
goto unlock;
|
|
}
|
|
|
|
if (_is_cpu_device(dev)) {
|
|
if (!cpus) {
|
|
dev_err(dev, "EM: invalid CPU mask\n");
|
|
ret = -EINVAL;
|
|
goto unlock;
|
|
}
|
|
|
|
for_each_cpu(cpu, cpus) {
|
|
if (em_cpu_get(cpu)) {
|
|
dev_err(dev, "EM: exists for CPU%d\n", cpu);
|
|
ret = -EEXIST;
|
|
goto unlock;
|
|
}
|
|
/*
|
|
* All CPUs of a domain must have the same
|
|
* micro-architecture since they all share the same
|
|
* table.
|
|
*/
|
|
cap = arch_scale_cpu_capacity(cpu);
|
|
if (prev_cap && prev_cap != cap) {
|
|
dev_err(dev, "EM: CPUs of %*pbl must have the same capacity\n",
|
|
cpumask_pr_args(cpus));
|
|
|
|
ret = -EINVAL;
|
|
goto unlock;
|
|
}
|
|
prev_cap = cap;
|
|
}
|
|
}
|
|
|
|
ret = em_create_pd(dev, nr_states, cb, cpus);
|
|
if (ret)
|
|
goto unlock;
|
|
|
|
dev->em_pd->milliwatts = milliwatts;
|
|
|
|
em_debug_create_pd(dev);
|
|
dev_info(dev, "EM: created perf domain\n");
|
|
|
|
unlock:
|
|
mutex_unlock(&em_pd_mutex);
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL_GPL(em_dev_register_perf_domain);
|
|
|
|
/**
|
|
* em_dev_unregister_perf_domain() - Unregister Energy Model (EM) for a device
|
|
* @dev : Device for which the EM is registered
|
|
*
|
|
* Unregister the EM for the specified @dev (but not a CPU device).
|
|
*/
|
|
void em_dev_unregister_perf_domain(struct device *dev)
|
|
{
|
|
if (IS_ERR_OR_NULL(dev) || !dev->em_pd)
|
|
return;
|
|
|
|
if (_is_cpu_device(dev))
|
|
return;
|
|
|
|
/*
|
|
* The mutex separates all register/unregister requests and protects
|
|
* from potential clean-up/setup issues in the debugfs directories.
|
|
* The debugfs directory name is the same as device's name.
|
|
*/
|
|
mutex_lock(&em_pd_mutex);
|
|
em_debug_remove_pd(dev);
|
|
|
|
kfree(dev->em_pd->table);
|
|
kfree(dev->em_pd);
|
|
dev->em_pd = NULL;
|
|
mutex_unlock(&em_pd_mutex);
|
|
}
|
|
EXPORT_SYMBOL_GPL(em_dev_unregister_perf_domain);
|