Changes in 5.15.75
Revert "fs: check FMODE_LSEEK to control internal pipe splicing"
ALSA: oss: Fix potential deadlock at unregistration
ALSA: rawmidi: Drop register_mutex in snd_rawmidi_free()
ALSA: usb-audio: Fix potential memory leaks
ALSA: usb-audio: Fix NULL dererence at error path
ALSA: hda/realtek: remove ALC289_FIXUP_DUAL_SPK for Dell 5530
ALSA: hda/realtek: Correct pin configs for ASUS G533Z
ALSA: hda/realtek: Add quirk for ASUS GV601R laptop
ALSA: hda/realtek: Add Intel Reference SSID to support headset keys
mtd: rawnand: atmel: Unmap streaming DMA mappings
io_uring/net: don't update msg_name if not provided
hv_netvsc: Fix race between VF offering and VF association message from host
cifs: destage dirty pages before re-reading them for cache=none
cifs: Fix the error length of VALIDATE_NEGOTIATE_INFO message
iio: dac: ad5593r: Fix i2c read protocol requirements
iio: ltc2497: Fix reading conversion results
iio: adc: ad7923: fix channel readings for some variants
iio: pressure: dps310: Refactor startup procedure
iio: pressure: dps310: Reset chip after timeout
xhci: dbc: Fix memory leak in xhci_alloc_dbc()
usb: add quirks for Lenovo OneLink+ Dock
can: kvaser_usb: Fix use of uninitialized completion
can: kvaser_usb_leaf: Fix overread with an invalid command
can: kvaser_usb_leaf: Fix TX queue out of sync after restart
can: kvaser_usb_leaf: Fix CAN state after restart
mmc: sdhci-sprd: Fix minimum clock limit
i2c: designware: Fix handling of real but unexpected device interrupts
fs: dlm: fix race between test_bit() and queue_work()
fs: dlm: handle -EBUSY first in lock arg validation
HID: multitouch: Add memory barriers
quota: Check next/prev free block number after reading from quota file
platform/chrome: cros_ec_proto: Update version on GET_NEXT_EVENT failure
ASoC: wcd9335: fix order of Slimbus unprepare/disable
ASoC: wcd934x: fix order of Slimbus unprepare/disable
hwmon: (gsc-hwmon) Call of_node_get() before of_find_xxx API
net: thunderbolt: Enable DMA paths only after rings are enabled
regulator: qcom_rpm: Fix circular deferral regression
arm64: topology: move store_cpu_topology() to shared code
riscv: topology: fix default topology reporting
RISC-V: Make port I/O string accessors actually work
parisc: fbdev/stifb: Align graphics memory size to 4MB
riscv: Allow PROT_WRITE-only mmap()
riscv: Make VM_WRITE imply VM_READ
riscv: always honor the CONFIG_CMDLINE_FORCE when parsing dtb
riscv: Pass -mno-relax only on lld < 15.0.0
UM: cpuinfo: Fix a warning for CONFIG_CPUMASK_OFFSTACK
nvmem: core: Fix memleak in nvmem_register()
nvme-multipath: fix possible hang in live ns resize with ANA access
nvme-pci: set min_align_mask before calculating max_hw_sectors
Revert "drm/amdgpu: use dirty framebuffer helper"
dmaengine: mxs: use platform_driver_register
drm/virtio: Check whether transferred 2D BO is shmem
drm/virtio: Unlock reservations on virtio_gpu_object_shmem_init() error
drm/virtio: Use appropriate atomic state in virtio_gpu_plane_cleanup_fb()
drm/udl: Restore display mode on resume
arm64: errata: Add Cortex-A55 to the repeat tlbi list
mm/damon: validate if the pmd entry is present before accessing
mm/mmap: undo ->mmap() when arch_validate_flags() fails
xen/gntdev: Prevent leaking grants
xen/gntdev: Accommodate VMA splitting
PCI: Sanitise firmware BAR assignments behind a PCI-PCI bridge
serial: 8250: Let drivers request full 16550A feature probing
serial: 8250: Request full 16550A feature probing for OxSemi PCIe devices
NFSD: Protect against send buffer overflow in NFSv3 READDIR
NFSD: Protect against send buffer overflow in NFSv2 READ
NFSD: Protect against send buffer overflow in NFSv3 READ
powercap: intel_rapl: Use standard Energy Unit for SPR Dram RAPL domain
powerpc/boot: Explicitly disable usage of SPE instructions
slimbus: qcom-ngd: use correct error in message of pdr_add_lookup() failure
slimbus: qcom-ngd: cleanup in probe error path
scsi: qedf: Populate sysfs attributes for vport
gpio: rockchip: request GPIO mux to pinctrl when setting direction
pinctrl: rockchip: add pinmux_ops.gpio_set_direction callback
fbdev: smscufx: Fix use-after-free in ufx_ops_open()
ksmbd: fix endless loop when encryption for response fails
ksmbd: Fix wrong return value and message length check in smb2_ioctl()
ksmbd: Fix user namespace mapping
fs: record I_DIRTY_TIME even if inode already has I_DIRTY_INODE
btrfs: fix race between quota enable and quota rescan ioctl
btrfs: set generation before calling btrfs_clean_tree_block in btrfs_init_new_buffer
f2fs: complete checkpoints during remount
f2fs: flush pending checkpoints when freezing super
f2fs: increase the limit for reserve_root
f2fs: fix to do sanity check on destination blkaddr during recovery
f2fs: fix to do sanity check on summary info
hardening: Avoid harmless Clang option under CONFIG_INIT_STACK_ALL_ZERO
hardening: Remove Clang's enable flag for -ftrivial-auto-var-init=zero
jbd2: wake up journal waiters in FIFO order, not LIFO
jbd2: fix potential buffer head reference count leak
jbd2: fix potential use-after-free in jbd2_fc_wait_bufs
jbd2: add miss release buffer head in fc_do_one_pass()
ext4: avoid crash when inline data creation follows DIO write
ext4: fix null-ptr-deref in ext4_write_info
ext4: make ext4_lazyinit_thread freezable
ext4: fix check for block being out of directory size
ext4: don't increase iversion counter for ea_inodes
ext4: ext4_read_bh_lock() should submit IO if the buffer isn't uptodate
ext4: place buffer head allocation before handle start
ext4: fix dir corruption when ext4_dx_add_entry() fails
ext4: fix miss release buffer head in ext4_fc_write_inode
ext4: fix potential memory leak in ext4_fc_record_modified_inode()
ext4: fix potential memory leak in ext4_fc_record_regions()
ext4: update 'state->fc_regions_size' after successful memory allocation
livepatch: fix race between fork and KLP transition
ftrace: Properly unset FTRACE_HASH_FL_MOD
ring-buffer: Allow splice to read previous partially read pages
ring-buffer: Have the shortest_full queue be the shortest not longest
ring-buffer: Check pending waiters when doing wake ups as well
ring-buffer: Add ring_buffer_wake_waiters()
ring-buffer: Fix race between reset page and reading page
tracing: Disable interrupt or preemption before acquiring arch_spinlock_t
tracing: Wake up ring buffer waiters on closing of the file
tracing: Wake up waiters when tracing is disabled
tracing: Add ioctl() to force ring buffer waiters to wake up
tracing: Move duplicate code of trace_kprobe/eprobe.c into header
tracing: Add "(fault)" name injection to kernel probes
tracing: Fix reading strings from synthetic events
thunderbolt: Explicitly enable lane adapter hotplug events at startup
efi: libstub: drop pointless get_memory_map() call
media: cedrus: Set the platform driver data earlier
media: cedrus: Fix endless loop in cedrus_h265_skip_bits()
blk-wbt: call rq_qos_add() after wb_normal is initialized
KVM: x86/emulator: Fix handing of POP SS to correctly set interruptibility
KVM: nVMX: Unconditionally purge queued/injected events on nested "exit"
KVM: nVMX: Don't propagate vmcs12's PERF_GLOBAL_CTRL settings to vmcs02
KVM: VMX: Drop bits 31:16 when shoving exception error code into VMCS
staging: greybus: audio_helper: remove unused and wrong debugfs usage
drm/nouveau/kms/nv140-: Disable interlacing
drm/nouveau: fix a use-after-free in nouveau_gem_prime_import_sg_table()
drm/i915: Fix watermark calculations for gen12+ RC CCS modifier
drm/i915: Fix watermark calculations for gen12+ MC CCS modifier
drm/i915: Fix watermark calculations for gen12+ CCS+CC modifier
drm/amd/display: Fix vblank refcount in vrr transition
smb3: must initialize two ACL struct fields to zero
selinux: use "grep -E" instead of "egrep"
ima: fix blocking of security.ima xattrs of unsupported algorithms
userfaultfd: open userfaultfds with O_RDONLY
ntfs3: rework xattr handlers and switch to POSIX ACL VFS helpers
thermal: cpufreq_cooling: Check the policy first in cpufreq_cooling_register()
sh: machvec: Use char[] for section boundaries
MIPS: SGI-IP27: Free some unused memory
MIPS: SGI-IP27: Fix platform-device leak in bridge_platform_create()
ARM: 9244/1: dump: Fix wrong pg_level in walk_pmd()
ARM: 9247/1: mm: set readonly for MT_MEMORY_RO with ARM_LPAE
objtool: Preserve special st_shndx indexes in elf_update_symbol
nfsd: Fix a memory leak in an error handling path
SUNRPC: Fix svcxdr_init_decode's end-of-buffer calculation
SUNRPC: Fix svcxdr_init_encode's buflen calculation
NFSD: Protect against send buffer overflow in NFSv2 READDIR
NFSD: Fix handling of oversized NFSv4 COMPOUND requests
wifi: rtlwifi: 8192de: correct checking of IQK reload
wifi: ath10k: add peer map clean up for peer delete in ath10k_sta_state()
leds: lm3601x: Don't use mutex after it was destroyed
bpf: Fix reference state management for synchronous callbacks
wifi: mac80211: allow bw change during channel switch in mesh
bpftool: Fix a wrong type cast in btf_dumper_int
spi: mt7621: Fix an error message in mt7621_spi_probe()
x86/resctrl: Fix to restore to original value when re-enabling hardware prefetch register
xsk: Fix backpressure mechanism on Tx
bpf: Disable preemption when increasing per-cpu map_locked
bpf: Propagate error from htab_lock_bucket() to userspace
bpf: Use this_cpu_{inc|dec|inc_return} for bpf_task_storage_busy
Bluetooth: btusb: mediatek: fix WMT failure during runtime suspend
wifi: rtl8xxxu: tighten bounds checking in rtl8xxxu_read_efuse()
wifi: rtw88: add missing destroy_workqueue() on error path in rtw_core_init()
selftests/xsk: Avoid use-after-free on ctx
spi: qup: add missing clk_disable_unprepare on error in spi_qup_resume()
spi: qup: add missing clk_disable_unprepare on error in spi_qup_pm_resume_runtime()
wifi: rtl8xxxu: Fix skb misuse in TX queue selection
spi: meson-spicc: do not rely on busy flag in pow2 clk ops
bpf: btf: fix truncated last_member_type_id in btf_struct_resolve
wifi: rtl8xxxu: gen2: Fix mistake in path B IQ calibration
wifi: rtl8xxxu: Remove copy-paste leftover in gen2_update_rate_mask
wifi: mt76: sdio: fix transmitting packet hangs
wifi: mt76: mt7615: add mt7615_mutex_acquire/release in mt7615_sta_set_decap_offload
wifi: mt76: mt7915: do not check state before configuring implicit beamform
Bluetooth: RFCOMM: Fix possible deadlock on socket shutdown/release
net: fs_enet: Fix wrong check in do_pd_setup
bpf: Ensure correct locking around vulnerable function find_vpid()
Bluetooth: hci_{ldisc,serdev}: check percpu_init_rwsem() failure
netfilter: conntrack: fix the gc rescheduling delay
netfilter: conntrack: revisit the gc initial rescheduling bias
wifi: ath11k: fix number of VHT beamformee spatial streams
x86/microcode/AMD: Track patch allocation size explicitly
x86/cpu: Include the header of init_ia32_feat_ctl()'s prototype
spi: dw: Fix PM disable depth imbalance in dw_spi_bt1_probe
spi/omap100k:Fix PM disable depth imbalance in omap1_spi100k_probe
skmsg: Schedule psock work if the cached skb exists on the psock
i2c: mlxbf: support lock mechanism
Bluetooth: hci_core: Fix not handling link timeouts propertly
xfrm: Reinject transport-mode packets through workqueue
netfilter: nft_fib: Fix for rpath check with VRF devices
spi: s3c64xx: Fix large transfers with DMA
wifi: rtl8xxxu: Fix AIFS written to REG_EDCA_*_PARAM
vhost/vsock: Use kvmalloc/kvfree for larger packets.
eth: alx: take rtnl_lock on resume
mISDN: fix use-after-free bugs in l1oip timer handlers
sctp: handle the error returned from sctp_auth_asoc_init_active_key
tcp: fix tcp_cwnd_validate() to not forget is_cwnd_limited
spi: Ensure that sg_table won't be used after being freed
hwmon: (pmbus/mp2888) Fix sensors readouts for MPS Multi-phase mp2888 controller
net: rds: don't hold sock lock when cancelling work from rds_tcp_reset_callbacks()
bnx2x: fix potential memory leak in bnx2x_tpa_stop()
net: wwan: iosm: Call mutex_init before locking it
net/ieee802154: reject zero-sized raw_sendmsg()
once: add DO_ONCE_SLOW() for sleepable contexts
net: mvpp2: fix mvpp2 debugfs leak
drm: bridge: adv7511: fix CEC power down control register offset
drm: bridge: adv7511: unregister cec i2c device after cec adapter
drm/bridge: Avoid uninitialized variable warning
drm/mipi-dsi: Detach devices when removing the host
drm/virtio: Correct drm_gem_shmem_get_sg_table() error handling
drm/bridge: parade-ps8640: Fix regulator supply order
drm/dp_mst: fix drm_dp_dpcd_read return value checks
drm:pl111: Add of_node_put() when breaking out of for_each_available_child_of_node()
ASoC: mt6359: fix tests for platform_get_irq() failure
platform/chrome: fix double-free in chromeos_laptop_prepare()
platform/chrome: fix memory corruption in ioctl
ASoC: tas2764: Allow mono streams
ASoC: tas2764: Drop conflicting set_bias_level power setting
ASoC: tas2764: Fix mute/unmute
platform/x86: msi-laptop: Fix old-ec check for backlight registering
platform/x86: msi-laptop: Fix resource cleanup
platform/chrome: cros_ec_typec: Correct alt mode index
drm/amdgpu: add missing pci_disable_device() in amdgpu_pmops_runtime_resume()
drm/bridge: megachips: Fix a null pointer dereference bug
ASoC: rsnd: Add check for rsnd_mod_power_on
ALSA: hda: beep: Simplify keep-power-at-enable behavior
drm/bochs: fix blanking
drm/omap: dss: Fix refcount leak bugs
drm/amdgpu: Fix memory leak in hpd_rx_irq_create_workqueue()
mmc: au1xmmc: Fix an error handling path in au1xmmc_probe()
ASoC: eureka-tlv320: Hold reference returned from of_find_xxx API
drm/msm/dpu: index dpu_kms->hw_vbif using vbif_idx
drm/msm/dp: correct 1.62G link rate at dp_catalog_ctrl_config_msa()
drm/vmwgfx: Fix memory leak in vmw_mksstat_add_ioctl()
ASoC: codecs: tx-macro: fix kcontrol put
ASoC: da7219: Fix an error handling path in da7219_register_dai_clks()
ALSA: dmaengine: increment buffer pointer atomically
mmc: wmt-sdmmc: Fix an error handling path in wmt_mci_probe()
ASoC: wm8997: Fix PM disable depth imbalance in wm8997_probe
ASoC: wm5110: Fix PM disable depth imbalance in wm5110_probe
ASoC: wm5102: Fix PM disable depth imbalance in wm5102_probe
ASoC: mt6660: Fix PM disable depth imbalance in mt6660_i2c_probe
ALSA: hda/hdmi: Don't skip notification handling during PM operation
memory: pl353-smc: Fix refcount leak bug in pl353_smc_probe()
memory: of: Fix refcount leak bug in of_get_ddr_timings()
memory: of: Fix refcount leak bug in of_lpddr3_get_ddr_timings()
locks: fix TOCTOU race when granting write lease
soc: qcom: smsm: Fix refcount leak bugs in qcom_smsm_probe()
soc: qcom: smem_state: Add refcounting for the 'state->of_node'
ARM: dts: imx6qdl-kontron-samx6i: hook up DDC i2c bus
ARM: dts: turris-omnia: Fix mpp26 pin name and comment
ARM: dts: kirkwood: lsxl: fix serial line
ARM: dts: kirkwood: lsxl: remove first ethernet port
ia64: export memory_add_physaddr_to_nid to fix cxl build error
soc/tegra: fuse: Drop Kconfig dependency on TEGRA20_APB_DMA
arm64: dts: ti: k3-j7200: fix main pinmux range
ARM: dts: exynos: correct s5k6a3 reset polarity on Midas family
ARM: Drop CMDLINE_* dependency on ATAGS
ext4: don't run ext4lazyinit for read-only filesystems
arm64: ftrace: fix module PLTs with mcount
ARM: dts: exynos: fix polarity of VBUS GPIO of Origen
iio: adc: at91-sama5d2_adc: fix AT91_SAMA5D2_MR_TRACKTIM_MAX
iio: adc: at91-sama5d2_adc: check return status for pressure and touch
iio: adc: at91-sama5d2_adc: lock around oversampling and sample freq
iio: adc: at91-sama5d2_adc: disable/prepare buffer on suspend/resume
iio: inkern: only release the device node when done with it
iio: inkern: fix return value in devm_of_iio_channel_get_by_name()
iio: ABI: Fix wrong format of differential capacitance channel ABI.
iio: magnetometer: yas530: Change data type of hard_offsets to signed
RDMA/mlx5: Don't compare mkey tags in DEVX indirect mkey
usb: common: debug: Check non-standard control requests
clk: meson: Hold reference returned by of_get_parent()
clk: oxnas: Hold reference returned by of_get_parent()
clk: qoriq: Hold reference returned by of_get_parent()
clk: berlin: Add of_node_put() for of_get_parent()
clk: sprd: Hold reference returned by of_get_parent()
clk: tegra: Fix refcount leak in tegra210_clock_init
clk: tegra: Fix refcount leak in tegra114_clock_init
clk: tegra20: Fix refcount leak in tegra20_clock_init
HSI: omap_ssi: Fix refcount leak in ssi_probe
HSI: omap_ssi_port: Fix dma_map_sg error check
media: exynos4-is: fimc-is: Add of_node_put() when breaking out of loop
tty: xilinx_uartps: Fix the ignore_status
media: meson: vdec: add missing clk_disable_unprepare on error in vdec_hevc_start()
media: uvcvideo: Fix memory leak in uvc_gpio_parse
media: uvcvideo: Use entity get_cur in uvc_ctrl_set
media: xilinx: vipp: Fix refcount leak in xvip_graph_dma_init
RDMA/rxe: Fix "kernel NULL pointer dereference" error
RDMA/rxe: Fix the error caused by qp->sk
misc: ocxl: fix possible refcount leak in afu_ioctl()
fpga: prevent integer overflow in dfl_feature_ioctl_set_irq()
dmaengine: hisilicon: Disable channels when unregister hisi_dma
dmaengine: hisilicon: Fix CQ head update
dmaengine: hisilicon: Add multi-thread support for a DMA channel
dyndbg: fix static_branch manipulation
dyndbg: fix module.dyndbg handling
dyndbg: let query-modname override actual module name
dyndbg: drop EXPORTed dynamic_debug_exec_queries
clk: qcom: sm6115: Select QCOM_GDSC
mtd: devices: docg3: check the return value of devm_ioremap() in the probe
phy: amlogic: phy-meson-axg-mipi-pcie-analog: Hold reference returned by of_get_parent()
phy: phy-mtk-tphy: fix the phy type setting issue
mtd: rawnand: intel: Read the chip-select line from the correct OF node
mtd: rawnand: intel: Remove undocumented compatible string
mtd: rawnand: fsl_elbc: Fix none ECC mode
RDMA/irdma: Align AE id codes to correct flush code and event
RDMA/srp: Fix srp_abort()
RDMA/siw: Always consume all skbuf data in sk_data_ready() upcall.
RDMA/siw: Fix QP destroy to wait for all references dropped.
ata: fix ata_id_sense_reporting_enabled() and ata_id_has_sense_reporting()
ata: fix ata_id_has_devslp()
ata: fix ata_id_has_ncq_autosense()
ata: fix ata_id_has_dipm()
mtd: rawnand: meson: fix bit map use in meson_nfc_ecc_correct()
md: Replace snprintf with scnprintf
md/raid5: Ensure stripe_fill happens on non-read IO with journal
md/raid5: Remove unnecessary bio_put() in raid5_read_one_chunk()
RDMA/cm: Use SLID in the work completion as the DLID in responder side
IB: Set IOVA/LENGTH on IB_MR in core/uverbs layers
xhci: Don't show warning for reinit on known broken suspend
usb: gadget: function: fix dangling pnp_string in f_printer.c
drivers: serial: jsm: fix some leaks in probe
serial: 8250: Toggle IER bits on only after irq has been set up
tty: serial: fsl_lpuart: disable dma rx/tx use flags in lpuart_dma_shutdown
phy: qualcomm: call clk_disable_unprepare in the error handling
staging: vt6655: fix some erroneous memory clean-up loops
slimbus: qcom-ngd-ctrl: allow compile testing without QCOM_RPROC_COMMON
firmware: google: Test spinlock on panic path to avoid lockups
serial: 8250: Fix restoring termios speed after suspend
scsi: libsas: Fix use-after-free bug in smp_execute_task_sg()
scsi: iscsi: Rename iscsi_conn_queue_work()
scsi: iscsi: Add recv workqueue helpers
scsi: iscsi: Run recv path from workqueue
scsi: iscsi: iscsi_tcp: Fix null-ptr-deref while calling getpeername()
clk: qcom: apss-ipq6018: mark apcs_alias0_core_clk as critical
clk: qcom: gcc-sm6115: Override default Alpha PLL regs
RDMA/rxe: Fix resize_finish() in rxe_queue.c
fsi: core: Check error number after calling ida_simple_get
mfd: intel_soc_pmic: Fix an error handling path in intel_soc_pmic_i2c_probe()
mfd: fsl-imx25: Fix an error handling path in mx25_tsadc_setup_irq()
mfd: lp8788: Fix an error handling path in lp8788_probe()
mfd: lp8788: Fix an error handling path in lp8788_irq_init() and lp8788_irq_init()
mfd: fsl-imx25: Fix check for platform_get_irq() errors
mfd: sm501: Add check for platform_driver_register()
clk: mediatek: mt8183: mfgcfg: Propagate rate changes to parent
dmaengine: ioat: stop mod_timer from resurrecting deleted timer in __cleanup()
usb: mtu3: fix failed runtime suspend in host only mode
spmi: pmic-arb: correct duplicate APID to PPID mapping logic
clk: vc5: Fix 5P49V6901 outputs disabling when enabling FOD
clk: baikal-t1: Fix invalid xGMAC PTP clock divider
clk: baikal-t1: Add shared xGMAC ref/ptp clocks internal parent
clk: baikal-t1: Add SATA internal ref clock buffer
clk: bcm2835: fix bcm2835_clock_rate_from_divisor declaration
clk: imx: scu: fix memleak on platform_device_add() fails
clk: ti: dra7-atl: Fix reference leak in of_dra7_atl_clk_probe
clk: ast2600: BCLK comes from EPLL
mailbox: mpfs: fix handling of the reg property
mailbox: mpfs: account for mbox offsets while sending
mailbox: bcm-ferxrm-mailbox: Fix error check for dma_map_sg
powerpc/configs: Properly enable PAPR_SCM in pseries_defconfig
powerpc/math_emu/efp: Include module.h
powerpc/sysdev/fsl_msi: Add missing of_node_put()
powerpc/pci_dn: Add missing of_node_put()
powerpc/powernv: add missing of_node_put() in opal_export_attrs()
powerpc: Fix fallocate and fadvise64_64 compat parameter combination
x86/hyperv: Fix 'struct hv_enlightened_vmcs' definition
powerpc/64s: Fix GENERIC_CPU build flags for PPC970 / G5
powerpc: Fix SPE Power ISA properties for e500v1 platforms
powerpc/kprobes: Fix null pointer reference in arch_prepare_kprobe()
powerpc/pseries/vas: Pass hw_cpu_id to node associativity HCALL
crypto: sahara - don't sleep when in softirq
crypto: hisilicon/zip - fix mismatch in get/set sgl_sge_nr
hwrng: arm-smccc-trng - fix NO_ENTROPY handling
cgroup: Honor caller's cgroup NS when resolving path
hwrng: imx-rngc - Moving IRQ handler registering after imx_rngc_irq_mask_clear()
crypto: qat - fix default value of WDT timer
crypto: hisilicon/qm - fix missing put dfx access
cgroup/cpuset: Enable update_tasks_cpumask() on top_cpuset
iommu/omap: Fix buffer overflow in debugfs
crypto: akcipher - default implementation for setting a private key
crypto: ccp - Release dma channels before dmaengine unrgister
crypto: inside-secure - Change swab to swab32
crypto: qat - fix DMA transfer direction
cifs: return correct error in ->calc_signature()
iommu/iova: Fix module config properly
tracing: kprobe: Fix kprobe event gen test module on exit
tracing: kprobe: Make gen test module work in arm and riscv
tracing/osnoise: Fix possible recursive locking in stop_per_cpu_kthreads
kbuild: remove the target in signal traps when interrupted
kbuild: rpm-pkg: fix breakage when V=1 is used
crypto: marvell/octeontx - prevent integer overflows
crypto: cavium - prevent integer overflow loading firmware
thermal/drivers/qcom/tsens-v0_1: Fix MSM8939 fourth sensor hw_id
ACPI: APEI: do not add task_work to kernel thread to avoid memory leak
f2fs: fix race condition on setting FI_NO_EXTENT flag
f2fs: fix to account FS_CP_DATA_IO correctly
selftest: tpm2: Add Client.__del__() to close /dev/tpm* handle
fs: dlm: fix race in lowcomms
rcu: Avoid triggering strict-GP irq-work when RCU is idle
rcu: Back off upon fill_page_cache_func() allocation failure
rcu-tasks: Convert RCU_LOCKDEP_WARN() to WARN_ONCE()
ACPI: video: Add Toshiba Satellite/Portege Z830 quirk
ACPI: tables: FPDT: Don't call acpi_os_map_memory() on invalid phys address
cpufreq: intel_pstate: Add Tigerlake support in no-HWP mode
MIPS: BCM47XX: Cast memcmp() of function to (void *)
powercap: intel_rapl: fix UBSAN shift-out-of-bounds issue
thermal: intel_powerclamp: Use get_cpu() instead of smp_processor_id() to avoid crash
ARM: decompressor: Include .data.rel.ro.local
ACPI: x86: Add a quirk for Dell Inspiron 14 2-in-1 for StorageD3Enable
x86/entry: Work around Clang __bdos() bug
NFSD: Return nfserr_serverfault if splice_ok but buf->pages have data
NFSD: fix use-after-free on source server when doing inter-server copy
wifi: brcmfmac: fix invalid address access when enabling SCAN log level
bpftool: Clear errno after libcap's checks
ice: set tx_tstamps when creating new Tx rings via ethtool
net: ethernet: ti: davinci_mdio: Add workaround for errata i2329
openvswitch: Fix double reporting of drops in dropwatch
openvswitch: Fix overreporting of drops in dropwatch
tcp: annotate data-race around tcp_md5sig_pool_populated
x86/mce: Retrieve poison range from hardware
wifi: ath9k: avoid uninit memory read in ath9k_htc_rx_msg()
thunderbolt: Add back Intel Falcon Ridge end-to-end flow control workaround
xfrm: Update ipcomp_scratches with NULL when freed
iavf: Fix race between iavf_close and iavf_reset_task
wifi: brcmfmac: fix use-after-free bug in brcmf_netdev_start_xmit()
Bluetooth: btintel: Mark Intel controller to support LE_STATES quirk
regulator: core: Prevent integer underflow
wifi: mt76: mt7921: reset msta->airtime_ac while clearing up hw value
Bluetooth: L2CAP: initialize delayed works at l2cap_chan_create()
Bluetooth: hci_sysfs: Fix attempting to call device_add multiple times
can: bcm: check the result of can_send() in bcm_can_tx()
wifi: rt2x00: don't run Rt5592 IQ calibration on MT7620
wifi: rt2x00: set correct TX_SW_CFG1 MAC register for MT7620
wifi: rt2x00: set VGC gain for both chains of MT7620
wifi: rt2x00: set SoC wmac clock register
wifi: rt2x00: correctly set BBP register 86 for MT7620
hwmon: (sht4x) do not overflow clamping operation on 32-bit platforms
net: If sock is dead don't access sock's sk_wq in sk_stream_wait_memory
Bluetooth: L2CAP: Fix user-after-free
r8152: Rate limit overflow messages
drm/nouveau/nouveau_bo: fix potential memory leak in nouveau_bo_alloc()
drm: Use size_t type for len variable in drm_copy_field()
drm: Prevent drm_copy_field() to attempt copying a NULL pointer
drm/komeda: Fix handling of atomic commits in the atomic_commit_tail hook
gpu: lontium-lt9611: Fix NULL pointer dereference in lt9611_connector_init()
drm/amd/display: fix overflow on MIN_I64 definition
udmabuf: Set ubuf->sg = NULL if the creation of sg table fails
drm: bridge: dw_hdmi: only trigger hotplug event on link change
ALSA: usb-audio: Register card at the last interface
drm/vc4: vec: Fix timings for VEC modes
drm: panel-orientation-quirks: Add quirk for Anbernic Win600
platform/chrome: cros_ec: Notify the PM of wake events during resume
platform/x86: msi-laptop: Change DMI match / alias strings to fix module autoloading
ASoC: SOF: pci: Change DMI match info to support all Chrome platforms
drm/amdgpu: fix initial connector audio value
drm/meson: reorder driver deinit sequence to fix use-after-free bug
drm/meson: explicitly remove aggregate driver at module unload time
mmc: sdhci-msm: add compatible string check for sdm670
drm/dp: Don't rewrite link config when setting phy test pattern
drm/amd/display: Remove interface for periodic interrupt 1
ARM: dts: imx7d-sdb: config the max pressure for tsc2046
ARM: dts: imx6q: add missing properties for sram
ARM: dts: imx6dl: add missing properties for sram
ARM: dts: imx6qp: add missing properties for sram
ARM: dts: imx6sl: add missing properties for sram
ARM: dts: imx6sll: add missing properties for sram
ARM: dts: imx6sx: add missing properties for sram
kselftest/arm64: Fix validatation termination record after EXTRA_CONTEXT
arm64: dts: imx8mq-librem5: Add bq25895 as max17055's power supply
btrfs: dump extra info if one free space cache has more bitmaps than it should
btrfs: scrub: try to fix super block errors
btrfs: don't print information about space cache or tree every remount
ARM: 9242/1: kasan: Only map modules if CONFIG_KASAN_VMALLOC=n
clk: zynqmp: Fix stack-out-of-bounds in strncpy`
media: cx88: Fix a null-ptr-deref bug in buffer_prepare()
media: platform: fix some double free in meson-ge2d and mtk-jpeg and s5p-mfc
clk: zynqmp: pll: rectify rate rounding in zynqmp_pll_round_rate
usb: host: xhci-plat: suspend and resume clocks
usb: host: xhci-plat: suspend/resume clks for brcm
dmaengine: ti: k3-udma: Reset UDMA_CHAN_RT byte counters to prevent overflow
scsi: 3w-9xxx: Avoid disabling device if failing to enable it
nbd: Fix hung when signal interrupts nbd_start_device_ioctl()
iommu/arm-smmu-v3: Make default domain type of HiSilicon PTT device to identity
power: supply: adp5061: fix out-of-bounds read in adp5061_get_chg_type()
staging: vt6655: fix potential memory leak
blk-throttle: prevent overflow while calculating wait time
ata: libahci_platform: Sanity check the DT child nodes number
bcache: fix set_at_max_writeback_rate() for multiple attached devices
soundwire: cadence: Don't overwrite msg->buf during write commands
soundwire: intel: fix error handling on dai registration issues
HID: roccat: Fix use-after-free in roccat_read()
eventfd: guard wake_up in eventfd fs calls as well
md/raid5: Wait for MD_SB_CHANGE_PENDING in raid5d
usb: host: xhci: Fix potential memory leak in xhci_alloc_stream_info()
usb: musb: Fix musb_gadget.c rxstate overflow bug
arm64: dts: imx8mp: Add snps,gfladj-refclk-lpm-sel quirk to USB nodes
usb: dwc3: core: Enable GUCTL1 bit 10 for fixing termination error after resume bug
Revert "usb: storage: Add quirk for Samsung Fit flash"
staging: rtl8723bs: fix potential memory leak in rtw_init_drv_sw()
staging: rtl8723bs: fix a potential memory leak in rtw_init_cmd_priv()
scsi: tracing: Fix compile error in trace_array calls when TRACING is disabled
ext2: Use kvmalloc() for group descriptor array
nvme: copy firmware_rev on each init
nvmet-tcp: add bounds check on Transfer Tag
usb: idmouse: fix an uninit-value in idmouse_open
clk: bcm2835: Make peripheral PLLC critical
clk: bcm2835: Round UART input clock up
perf intel-pt: Fix segfault in intel_pt_print_info() with uClibc
io_uring/af_unix: defer registered files gc to io_uring release
io_uring: correct pinned_vm accounting
io_uring/rw: fix short rw error handling
io_uring/rw: fix error'ed retry return values
io_uring/rw: fix unexpected link breakage
mm: hugetlb: fix UAF in hugetlb_handle_userfault
net: ieee802154: return -EINVAL for unknown addr type
ALSA: usb-audio: Fix last interface check for registration
blk-wbt: fix that 'rwb->wc' is always set to 1 in wbt_init()
net: ethernet: ti: davinci_mdio: fix build for mdio bitbang uses
Revert "net/ieee802154: reject zero-sized raw_sendmsg()"
net/ieee802154: don't warn zero-sized raw_sendmsg()
drm/amd/display: Fix build breakage with CONFIG_DEBUG_FS=n
Kconfig.debug: simplify the dependency of DEBUG_INFO_DWARF4/5
Kconfig.debug: add toolchain checks for DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT
lib/Kconfig.debug: Add check for non-constant .{s,u}leb128 support to DWARF5
ext4: continue to expand file system when the target size doesn't reach
thermal: intel_powerclamp: Use first online CPU as control_cpu
gcov: support GCC 12.1 and newer compilers
io-wq: Fix memory leak in worker creation
Linux 5.15.75
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Change-Id: Id3dfe8285e830d01df7adb33729e78a75c1cac1a
702 lines
20 KiB
C
702 lines
20 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* linux/drivers/thermal/cpufreq_cooling.c
|
|
*
|
|
* Copyright (C) 2012 Samsung Electronics Co., Ltd(http://www.samsung.com)
|
|
*
|
|
* Copyright (C) 2012-2018 Linaro Limited.
|
|
*
|
|
* Authors: Amit Daniel <amit.kachhap@linaro.org>
|
|
* Viresh Kumar <viresh.kumar@linaro.org>
|
|
*
|
|
*/
|
|
#include <linux/cpu.h>
|
|
#include <linux/cpufreq.h>
|
|
#include <linux/cpu_cooling.h>
|
|
#include <linux/device.h>
|
|
#include <linux/energy_model.h>
|
|
#include <linux/err.h>
|
|
#include <linux/export.h>
|
|
#include <linux/pm_opp.h>
|
|
#include <linux/pm_qos.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/thermal.h>
|
|
|
|
#include <trace/events/thermal.h>
|
|
#include <trace/hooks/thermal.h>
|
|
|
|
/*
|
|
* Cooling state <-> CPUFreq frequency
|
|
*
|
|
* Cooling states are translated to frequencies throughout this driver and this
|
|
* is the relation between them.
|
|
*
|
|
* Highest cooling state corresponds to lowest possible frequency.
|
|
*
|
|
* i.e.
|
|
* level 0 --> 1st Max Freq
|
|
* level 1 --> 2nd Max Freq
|
|
* ...
|
|
*/
|
|
|
|
/**
|
|
* struct time_in_idle - Idle time stats
|
|
* @time: previous reading of the absolute time that this cpu was idle
|
|
* @timestamp: wall time of the last invocation of get_cpu_idle_time_us()
|
|
*/
|
|
struct time_in_idle {
|
|
u64 time;
|
|
u64 timestamp;
|
|
};
|
|
|
|
/**
|
|
* struct cpufreq_cooling_device - data for cooling device with cpufreq
|
|
* @last_load: load measured by the latest call to cpufreq_get_requested_power()
|
|
* @cpufreq_state: integer value representing the current state of cpufreq
|
|
* cooling devices.
|
|
* @max_level: maximum cooling level. One less than total number of valid
|
|
* cpufreq frequencies.
|
|
* @em: Reference on the Energy Model of the device
|
|
* @cdev: thermal_cooling_device pointer to keep track of the
|
|
* registered cooling device.
|
|
* @policy: cpufreq policy.
|
|
* @idle_time: idle time stats
|
|
* @qos_req: PM QoS contraint to apply
|
|
*
|
|
* This structure is required for keeping information of each registered
|
|
* cpufreq_cooling_device.
|
|
*/
|
|
struct cpufreq_cooling_device {
|
|
u32 last_load;
|
|
unsigned int cpufreq_state;
|
|
unsigned int max_level;
|
|
struct em_perf_domain *em;
|
|
struct cpufreq_policy *policy;
|
|
#ifndef CONFIG_SMP
|
|
struct time_in_idle *idle_time;
|
|
#endif
|
|
struct freq_qos_request qos_req;
|
|
};
|
|
|
|
#ifdef CONFIG_THERMAL_GOV_POWER_ALLOCATOR
|
|
/**
|
|
* get_level: Find the level for a particular frequency
|
|
* @cpufreq_cdev: cpufreq_cdev for which the property is required
|
|
* @freq: Frequency
|
|
*
|
|
* Return: level corresponding to the frequency.
|
|
*/
|
|
static unsigned long get_level(struct cpufreq_cooling_device *cpufreq_cdev,
|
|
unsigned int freq)
|
|
{
|
|
int i;
|
|
|
|
for (i = cpufreq_cdev->max_level - 1; i >= 0; i--) {
|
|
if (freq > cpufreq_cdev->em->table[i].frequency)
|
|
break;
|
|
}
|
|
|
|
return cpufreq_cdev->max_level - i - 1;
|
|
}
|
|
|
|
static u32 cpu_freq_to_power(struct cpufreq_cooling_device *cpufreq_cdev,
|
|
u32 freq)
|
|
{
|
|
int i;
|
|
|
|
for (i = cpufreq_cdev->max_level - 1; i >= 0; i--) {
|
|
if (freq > cpufreq_cdev->em->table[i].frequency)
|
|
break;
|
|
}
|
|
|
|
return cpufreq_cdev->em->table[i + 1].power;
|
|
}
|
|
|
|
static u32 cpu_power_to_freq(struct cpufreq_cooling_device *cpufreq_cdev,
|
|
u32 power)
|
|
{
|
|
int i;
|
|
|
|
for (i = cpufreq_cdev->max_level; i > 0; i--) {
|
|
if (power >= cpufreq_cdev->em->table[i].power)
|
|
break;
|
|
}
|
|
|
|
return cpufreq_cdev->em->table[i].frequency;
|
|
}
|
|
|
|
/**
|
|
* get_load() - get load for a cpu
|
|
* @cpufreq_cdev: struct cpufreq_cooling_device for the cpu
|
|
* @cpu: cpu number
|
|
* @cpu_idx: index of the cpu in time_in_idle array
|
|
*
|
|
* Return: The average load of cpu @cpu in percentage since this
|
|
* function was last called.
|
|
*/
|
|
#ifdef CONFIG_SMP
|
|
static u32 get_load(struct cpufreq_cooling_device *cpufreq_cdev, int cpu,
|
|
int cpu_idx)
|
|
{
|
|
unsigned long max = arch_scale_cpu_capacity(cpu);
|
|
unsigned long util;
|
|
|
|
util = sched_cpu_util(cpu, max);
|
|
return (util * 100) / max;
|
|
}
|
|
#else /* !CONFIG_SMP */
|
|
static u32 get_load(struct cpufreq_cooling_device *cpufreq_cdev, int cpu,
|
|
int cpu_idx)
|
|
{
|
|
u32 load;
|
|
u64 now, now_idle, delta_time, delta_idle;
|
|
struct time_in_idle *idle_time = &cpufreq_cdev->idle_time[cpu_idx];
|
|
|
|
now_idle = get_cpu_idle_time(cpu, &now, 0);
|
|
delta_idle = now_idle - idle_time->time;
|
|
delta_time = now - idle_time->timestamp;
|
|
|
|
if (delta_time <= delta_idle)
|
|
load = 0;
|
|
else
|
|
load = div64_u64(100 * (delta_time - delta_idle), delta_time);
|
|
|
|
idle_time->time = now_idle;
|
|
idle_time->timestamp = now;
|
|
|
|
return load;
|
|
}
|
|
#endif /* CONFIG_SMP */
|
|
|
|
/**
|
|
* get_dynamic_power() - calculate the dynamic power
|
|
* @cpufreq_cdev: &cpufreq_cooling_device for this cdev
|
|
* @freq: current frequency
|
|
*
|
|
* Return: the dynamic power consumed by the cpus described by
|
|
* @cpufreq_cdev.
|
|
*/
|
|
static u32 get_dynamic_power(struct cpufreq_cooling_device *cpufreq_cdev,
|
|
unsigned long freq)
|
|
{
|
|
u32 raw_cpu_power;
|
|
|
|
raw_cpu_power = cpu_freq_to_power(cpufreq_cdev, freq);
|
|
return (raw_cpu_power * cpufreq_cdev->last_load) / 100;
|
|
}
|
|
|
|
/**
|
|
* cpufreq_get_requested_power() - get the current power
|
|
* @cdev: &thermal_cooling_device pointer
|
|
* @power: pointer in which to store the resulting power
|
|
*
|
|
* Calculate the current power consumption of the cpus in milliwatts
|
|
* and store it in @power. This function should actually calculate
|
|
* the requested power, but it's hard to get the frequency that
|
|
* cpufreq would have assigned if there were no thermal limits.
|
|
* Instead, we calculate the current power on the assumption that the
|
|
* immediate future will look like the immediate past.
|
|
*
|
|
* We use the current frequency and the average load since this
|
|
* function was last called. In reality, there could have been
|
|
* multiple opps since this function was last called and that affects
|
|
* the load calculation. While it's not perfectly accurate, this
|
|
* simplification is good enough and works. REVISIT this, as more
|
|
* complex code may be needed if experiments show that it's not
|
|
* accurate enough.
|
|
*
|
|
* Return: 0 on success, -E* if getting the static power failed.
|
|
*/
|
|
static int cpufreq_get_requested_power(struct thermal_cooling_device *cdev,
|
|
u32 *power)
|
|
{
|
|
unsigned long freq;
|
|
int i = 0, cpu;
|
|
u32 total_load = 0;
|
|
struct cpufreq_cooling_device *cpufreq_cdev = cdev->devdata;
|
|
struct cpufreq_policy *policy = cpufreq_cdev->policy;
|
|
u32 *load_cpu = NULL;
|
|
|
|
freq = cpufreq_quick_get(policy->cpu);
|
|
|
|
trace_android_vh_modify_thermal_request_freq(policy, &freq);
|
|
|
|
if (trace_thermal_power_cpu_get_power_enabled()) {
|
|
u32 ncpus = cpumask_weight(policy->related_cpus);
|
|
|
|
load_cpu = kcalloc(ncpus, sizeof(*load_cpu), GFP_KERNEL);
|
|
}
|
|
|
|
for_each_cpu(cpu, policy->related_cpus) {
|
|
u32 load;
|
|
|
|
if (cpu_online(cpu))
|
|
load = get_load(cpufreq_cdev, cpu, i);
|
|
else
|
|
load = 0;
|
|
|
|
total_load += load;
|
|
if (load_cpu)
|
|
load_cpu[i] = load;
|
|
|
|
i++;
|
|
}
|
|
|
|
cpufreq_cdev->last_load = total_load;
|
|
|
|
*power = get_dynamic_power(cpufreq_cdev, freq);
|
|
|
|
if (load_cpu) {
|
|
trace_thermal_power_cpu_get_power(policy->related_cpus, freq,
|
|
load_cpu, i, *power);
|
|
|
|
kfree(load_cpu);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* cpufreq_state2power() - convert a cpu cdev state to power consumed
|
|
* @cdev: &thermal_cooling_device pointer
|
|
* @state: cooling device state to be converted
|
|
* @power: pointer in which to store the resulting power
|
|
*
|
|
* Convert cooling device state @state into power consumption in
|
|
* milliwatts assuming 100% load. Store the calculated power in
|
|
* @power.
|
|
*
|
|
* Return: 0 on success, -EINVAL if the cooling device state could not
|
|
* be converted into a frequency or other -E* if there was an error
|
|
* when calculating the static power.
|
|
*/
|
|
static int cpufreq_state2power(struct thermal_cooling_device *cdev,
|
|
unsigned long state, u32 *power)
|
|
{
|
|
unsigned int freq, num_cpus, idx;
|
|
struct cpufreq_cooling_device *cpufreq_cdev = cdev->devdata;
|
|
|
|
/* Request state should be less than max_level */
|
|
if (state > cpufreq_cdev->max_level)
|
|
return -EINVAL;
|
|
|
|
num_cpus = cpumask_weight(cpufreq_cdev->policy->cpus);
|
|
|
|
idx = cpufreq_cdev->max_level - state;
|
|
freq = cpufreq_cdev->em->table[idx].frequency;
|
|
*power = cpu_freq_to_power(cpufreq_cdev, freq) * num_cpus;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* cpufreq_power2state() - convert power to a cooling device state
|
|
* @cdev: &thermal_cooling_device pointer
|
|
* @power: power in milliwatts to be converted
|
|
* @state: pointer in which to store the resulting state
|
|
*
|
|
* Calculate a cooling device state for the cpus described by @cdev
|
|
* that would allow them to consume at most @power mW and store it in
|
|
* @state. Note that this calculation depends on external factors
|
|
* such as the cpu load or the current static power. Calling this
|
|
* function with the same power as input can yield different cooling
|
|
* device states depending on those external factors.
|
|
*
|
|
* Return: 0 on success, -ENODEV if no cpus are online or -EINVAL if
|
|
* the calculated frequency could not be converted to a valid state.
|
|
* The latter should not happen unless the frequencies available to
|
|
* cpufreq have changed since the initialization of the cpu cooling
|
|
* device.
|
|
*/
|
|
static int cpufreq_power2state(struct thermal_cooling_device *cdev,
|
|
u32 power, unsigned long *state)
|
|
{
|
|
unsigned int target_freq;
|
|
u32 last_load, normalised_power;
|
|
struct cpufreq_cooling_device *cpufreq_cdev = cdev->devdata;
|
|
struct cpufreq_policy *policy = cpufreq_cdev->policy;
|
|
|
|
last_load = cpufreq_cdev->last_load ?: 1;
|
|
normalised_power = (power * 100) / last_load;
|
|
target_freq = cpu_power_to_freq(cpufreq_cdev, normalised_power);
|
|
|
|
trace_android_vh_modify_thermal_target_freq(policy, &target_freq);
|
|
|
|
*state = get_level(cpufreq_cdev, target_freq);
|
|
trace_thermal_power_cpu_limit(policy->related_cpus, target_freq, *state,
|
|
power);
|
|
return 0;
|
|
}
|
|
|
|
static inline bool em_is_sane(struct cpufreq_cooling_device *cpufreq_cdev,
|
|
struct em_perf_domain *em) {
|
|
struct cpufreq_policy *policy;
|
|
unsigned int nr_levels;
|
|
|
|
if (!em)
|
|
return false;
|
|
|
|
policy = cpufreq_cdev->policy;
|
|
if (!cpumask_equal(policy->related_cpus, em_span_cpus(em))) {
|
|
pr_err("The span of pd %*pbl is misaligned with cpufreq policy %*pbl\n",
|
|
cpumask_pr_args(em_span_cpus(em)),
|
|
cpumask_pr_args(policy->related_cpus));
|
|
return false;
|
|
}
|
|
|
|
nr_levels = cpufreq_cdev->max_level + 1;
|
|
if (em_pd_nr_perf_states(em) != nr_levels) {
|
|
pr_err("The number of performance states in pd %*pbl (%u) doesn't match the number of cooling levels (%u)\n",
|
|
cpumask_pr_args(em_span_cpus(em)),
|
|
em_pd_nr_perf_states(em), nr_levels);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
#endif /* CONFIG_THERMAL_GOV_POWER_ALLOCATOR */
|
|
|
|
#ifdef CONFIG_SMP
|
|
static inline int allocate_idle_time(struct cpufreq_cooling_device *cpufreq_cdev)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline void free_idle_time(struct cpufreq_cooling_device *cpufreq_cdev)
|
|
{
|
|
}
|
|
#else
|
|
static int allocate_idle_time(struct cpufreq_cooling_device *cpufreq_cdev)
|
|
{
|
|
unsigned int num_cpus = cpumask_weight(cpufreq_cdev->policy->related_cpus);
|
|
|
|
cpufreq_cdev->idle_time = kcalloc(num_cpus,
|
|
sizeof(*cpufreq_cdev->idle_time),
|
|
GFP_KERNEL);
|
|
if (!cpufreq_cdev->idle_time)
|
|
return -ENOMEM;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void free_idle_time(struct cpufreq_cooling_device *cpufreq_cdev)
|
|
{
|
|
kfree(cpufreq_cdev->idle_time);
|
|
cpufreq_cdev->idle_time = NULL;
|
|
}
|
|
#endif /* CONFIG_SMP */
|
|
|
|
static unsigned int get_state_freq(struct cpufreq_cooling_device *cpufreq_cdev,
|
|
unsigned long state)
|
|
{
|
|
struct cpufreq_policy *policy;
|
|
unsigned long idx;
|
|
|
|
#ifdef CONFIG_THERMAL_GOV_POWER_ALLOCATOR
|
|
/* Use the Energy Model table if available */
|
|
if (cpufreq_cdev->em) {
|
|
idx = cpufreq_cdev->max_level - state;
|
|
return cpufreq_cdev->em->table[idx].frequency;
|
|
}
|
|
#endif
|
|
|
|
/* Otherwise, fallback on the CPUFreq table */
|
|
policy = cpufreq_cdev->policy;
|
|
if (policy->freq_table_sorted == CPUFREQ_TABLE_SORTED_ASCENDING)
|
|
idx = cpufreq_cdev->max_level - state;
|
|
else
|
|
idx = state;
|
|
|
|
return policy->freq_table[idx].frequency;
|
|
}
|
|
|
|
/* cpufreq cooling device callback functions are defined below */
|
|
|
|
/**
|
|
* cpufreq_get_max_state - callback function to get the max cooling state.
|
|
* @cdev: thermal cooling device pointer.
|
|
* @state: fill this variable with the max cooling state.
|
|
*
|
|
* Callback for the thermal cooling device to return the cpufreq
|
|
* max cooling state.
|
|
*
|
|
* Return: 0 on success, an error code otherwise.
|
|
*/
|
|
static int cpufreq_get_max_state(struct thermal_cooling_device *cdev,
|
|
unsigned long *state)
|
|
{
|
|
struct cpufreq_cooling_device *cpufreq_cdev = cdev->devdata;
|
|
|
|
*state = cpufreq_cdev->max_level;
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* cpufreq_get_cur_state - callback function to get the current cooling state.
|
|
* @cdev: thermal cooling device pointer.
|
|
* @state: fill this variable with the current cooling state.
|
|
*
|
|
* Callback for the thermal cooling device to return the cpufreq
|
|
* current cooling state.
|
|
*
|
|
* Return: 0 on success, an error code otherwise.
|
|
*/
|
|
static int cpufreq_get_cur_state(struct thermal_cooling_device *cdev,
|
|
unsigned long *state)
|
|
{
|
|
struct cpufreq_cooling_device *cpufreq_cdev = cdev->devdata;
|
|
|
|
*state = cpufreq_cdev->cpufreq_state;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* cpufreq_set_cur_state - callback function to set the current cooling state.
|
|
* @cdev: thermal cooling device pointer.
|
|
* @state: set this variable to the current cooling state.
|
|
*
|
|
* Callback for the thermal cooling device to change the cpufreq
|
|
* current cooling state.
|
|
*
|
|
* Return: 0 on success, an error code otherwise.
|
|
*/
|
|
static int cpufreq_set_cur_state(struct thermal_cooling_device *cdev,
|
|
unsigned long state)
|
|
{
|
|
struct cpufreq_cooling_device *cpufreq_cdev = cdev->devdata;
|
|
struct cpumask *cpus;
|
|
unsigned int frequency;
|
|
unsigned long max_capacity, capacity;
|
|
int ret;
|
|
|
|
/* Request state should be less than max_level */
|
|
if (state > cpufreq_cdev->max_level)
|
|
return -EINVAL;
|
|
|
|
/* Check if the old cooling action is same as new cooling action */
|
|
if (cpufreq_cdev->cpufreq_state == state)
|
|
return 0;
|
|
|
|
frequency = get_state_freq(cpufreq_cdev, state);
|
|
|
|
ret = freq_qos_update_request(&cpufreq_cdev->qos_req, frequency);
|
|
if (ret >= 0) {
|
|
cpufreq_cdev->cpufreq_state = state;
|
|
cpus = cpufreq_cdev->policy->related_cpus;
|
|
max_capacity = arch_scale_cpu_capacity(cpumask_first(cpus));
|
|
capacity = frequency * max_capacity;
|
|
capacity /= cpufreq_cdev->policy->cpuinfo.max_freq;
|
|
arch_set_thermal_pressure(cpus, max_capacity - capacity);
|
|
ret = 0;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* Bind cpufreq callbacks to thermal cooling device ops */
|
|
|
|
static struct thermal_cooling_device_ops cpufreq_cooling_ops = {
|
|
.get_max_state = cpufreq_get_max_state,
|
|
.get_cur_state = cpufreq_get_cur_state,
|
|
.set_cur_state = cpufreq_set_cur_state,
|
|
};
|
|
|
|
/**
|
|
* __cpufreq_cooling_register - helper function to create cpufreq cooling device
|
|
* @np: a valid struct device_node to the cooling device device tree node
|
|
* @policy: cpufreq policy
|
|
* Normally this should be same as cpufreq policy->related_cpus.
|
|
* @em: Energy Model of the cpufreq policy
|
|
*
|
|
* This interface function registers the cpufreq cooling device with the name
|
|
* "thermal-cpufreq-%x". This api can support multiple instances of cpufreq
|
|
* cooling devices. It also gives the opportunity to link the cooling device
|
|
* with a device tree node, in order to bind it via the thermal DT code.
|
|
*
|
|
* Return: a valid struct thermal_cooling_device pointer on success,
|
|
* on failure, it returns a corresponding ERR_PTR().
|
|
*/
|
|
static struct thermal_cooling_device *
|
|
__cpufreq_cooling_register(struct device_node *np,
|
|
struct cpufreq_policy *policy,
|
|
struct em_perf_domain *em)
|
|
{
|
|
struct thermal_cooling_device *cdev;
|
|
struct cpufreq_cooling_device *cpufreq_cdev;
|
|
unsigned int i;
|
|
struct device *dev;
|
|
int ret;
|
|
struct thermal_cooling_device_ops *cooling_ops;
|
|
char *name;
|
|
|
|
if (IS_ERR_OR_NULL(policy)) {
|
|
pr_err("%s: cpufreq policy isn't valid: %p\n", __func__, policy);
|
|
return ERR_PTR(-EINVAL);
|
|
}
|
|
|
|
dev = get_cpu_device(policy->cpu);
|
|
if (unlikely(!dev)) {
|
|
pr_warn("No cpu device for cpu %d\n", policy->cpu);
|
|
return ERR_PTR(-ENODEV);
|
|
}
|
|
|
|
i = cpufreq_table_count_valid_entries(policy);
|
|
if (!i) {
|
|
pr_debug("%s: CPUFreq table not found or has no valid entries\n",
|
|
__func__);
|
|
return ERR_PTR(-ENODEV);
|
|
}
|
|
|
|
cpufreq_cdev = kzalloc(sizeof(*cpufreq_cdev), GFP_KERNEL);
|
|
if (!cpufreq_cdev)
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
cpufreq_cdev->policy = policy;
|
|
|
|
ret = allocate_idle_time(cpufreq_cdev);
|
|
if (ret) {
|
|
cdev = ERR_PTR(ret);
|
|
goto free_cdev;
|
|
}
|
|
|
|
/* max_level is an index, not a counter */
|
|
cpufreq_cdev->max_level = i - 1;
|
|
|
|
cooling_ops = &cpufreq_cooling_ops;
|
|
|
|
#ifdef CONFIG_THERMAL_GOV_POWER_ALLOCATOR
|
|
if (em_is_sane(cpufreq_cdev, em)) {
|
|
cpufreq_cdev->em = em;
|
|
cooling_ops->get_requested_power = cpufreq_get_requested_power;
|
|
cooling_ops->state2power = cpufreq_state2power;
|
|
cooling_ops->power2state = cpufreq_power2state;
|
|
} else
|
|
#endif
|
|
if (policy->freq_table_sorted == CPUFREQ_TABLE_UNSORTED) {
|
|
pr_err("%s: unsorted frequency tables are not supported\n",
|
|
__func__);
|
|
cdev = ERR_PTR(-EINVAL);
|
|
goto free_idle_time;
|
|
}
|
|
|
|
ret = freq_qos_add_request(&policy->constraints,
|
|
&cpufreq_cdev->qos_req, FREQ_QOS_MAX,
|
|
get_state_freq(cpufreq_cdev, 0));
|
|
if (ret < 0) {
|
|
pr_err("%s: Failed to add freq constraint (%d)\n", __func__,
|
|
ret);
|
|
cdev = ERR_PTR(ret);
|
|
goto free_idle_time;
|
|
}
|
|
|
|
cdev = ERR_PTR(-ENOMEM);
|
|
name = kasprintf(GFP_KERNEL, "cpufreq-%s", dev_name(dev));
|
|
if (!name)
|
|
goto remove_qos_req;
|
|
|
|
cdev = thermal_of_cooling_device_register(np, name, cpufreq_cdev,
|
|
cooling_ops);
|
|
kfree(name);
|
|
|
|
if (IS_ERR(cdev))
|
|
goto remove_qos_req;
|
|
|
|
return cdev;
|
|
|
|
remove_qos_req:
|
|
freq_qos_remove_request(&cpufreq_cdev->qos_req);
|
|
free_idle_time:
|
|
free_idle_time(cpufreq_cdev);
|
|
free_cdev:
|
|
kfree(cpufreq_cdev);
|
|
return cdev;
|
|
}
|
|
|
|
/**
|
|
* cpufreq_cooling_register - function to create cpufreq cooling device.
|
|
* @policy: cpufreq policy
|
|
*
|
|
* This interface function registers the cpufreq cooling device with the name
|
|
* "thermal-cpufreq-%x". This api can support multiple instances of cpufreq
|
|
* cooling devices.
|
|
*
|
|
* Return: a valid struct thermal_cooling_device pointer on success,
|
|
* on failure, it returns a corresponding ERR_PTR().
|
|
*/
|
|
struct thermal_cooling_device *
|
|
cpufreq_cooling_register(struct cpufreq_policy *policy)
|
|
{
|
|
return __cpufreq_cooling_register(NULL, policy, NULL);
|
|
}
|
|
EXPORT_SYMBOL_GPL(cpufreq_cooling_register);
|
|
|
|
/**
|
|
* of_cpufreq_cooling_register - function to create cpufreq cooling device.
|
|
* @policy: cpufreq policy
|
|
*
|
|
* This interface function registers the cpufreq cooling device with the name
|
|
* "thermal-cpufreq-%x". This api can support multiple instances of cpufreq
|
|
* cooling devices. Using this API, the cpufreq cooling device will be
|
|
* linked to the device tree node provided.
|
|
*
|
|
* Using this function, the cooling device will implement the power
|
|
* extensions by using a simple cpu power model. The cpus must have
|
|
* registered their OPPs using the OPP library.
|
|
*
|
|
* It also takes into account, if property present in policy CPU node, the
|
|
* static power consumed by the cpu.
|
|
*
|
|
* Return: a valid struct thermal_cooling_device pointer on success,
|
|
* and NULL on failure.
|
|
*/
|
|
struct thermal_cooling_device *
|
|
of_cpufreq_cooling_register(struct cpufreq_policy *policy)
|
|
{
|
|
struct device_node *np = of_get_cpu_node(policy->cpu, NULL);
|
|
struct thermal_cooling_device *cdev = NULL;
|
|
|
|
if (!np) {
|
|
pr_err("cpufreq_cooling: OF node not available for cpu%d\n",
|
|
policy->cpu);
|
|
return NULL;
|
|
}
|
|
|
|
if (of_find_property(np, "#cooling-cells", NULL)) {
|
|
struct em_perf_domain *em = em_cpu_get(policy->cpu);
|
|
|
|
cdev = __cpufreq_cooling_register(np, policy, em);
|
|
if (IS_ERR(cdev)) {
|
|
pr_err("cpufreq_cooling: cpu%d failed to register as cooling device: %ld\n",
|
|
policy->cpu, PTR_ERR(cdev));
|
|
cdev = NULL;
|
|
}
|
|
}
|
|
|
|
of_node_put(np);
|
|
return cdev;
|
|
}
|
|
EXPORT_SYMBOL_GPL(of_cpufreq_cooling_register);
|
|
|
|
/**
|
|
* cpufreq_cooling_unregister - function to remove cpufreq cooling device.
|
|
* @cdev: thermal cooling device pointer.
|
|
*
|
|
* This interface function unregisters the "thermal-cpufreq-%x" cooling device.
|
|
*/
|
|
void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
|
|
{
|
|
struct cpufreq_cooling_device *cpufreq_cdev;
|
|
|
|
if (!cdev)
|
|
return;
|
|
|
|
cpufreq_cdev = cdev->devdata;
|
|
|
|
thermal_cooling_device_unregister(cdev);
|
|
freq_qos_remove_request(&cpufreq_cdev->qos_req);
|
|
free_idle_time(cpufreq_cdev);
|
|
kfree(cpufreq_cdev);
|
|
}
|
|
EXPORT_SYMBOL_GPL(cpufreq_cooling_unregister);
|