cda8925044
* refs/heads/tmp-10f1d14: Linux 4.19.86 x86/resctrl: Fix rdt_find_domain() return value and checks mmc: tmio: fix SCC error handling to avoid false positive CRC error powerpc/time: Fix clockevent_decrementer initalisation for PR KVM tools: PCI: Fix broken pcitest compilation PM / devfreq: Fix static checker warning in try_then_request_governor ACPI / LPSS: Use acpi_lpss_* instead of acpi_subsys_* functions for hibernate tcp: start receiver buffer autotuning sooner ARM: dts: omap5: Fix dual-role mode on Super-Speed port mlxsw: spectrum_switchdev: Check notification relevance based on upper device spi: rockchip: initialize dma_slave_config properly mac80211: minstrel: fix sampling/reporting of CCK rates in HT mode mac80211: minstrel: fix CCK rate group streams value mac80211: minstrel: fix using short preamble CCK rates on HT clients misc: cxl: Fix possible null pointer dereference netfilter: nft_compat: do not dump private area net: sched: avoid writing on noop_qdisc selftests: forwarding: Have lldpad_app_wait_set() wait for unknown, too hwmon: (npcm-750-pwm-fan) Change initial pwm target to 255 hwmon: (ina3221) Fix INA3221_CONFIG_MODE macros hwmon: (pwm-fan) Silence error on probe deferral hwmon: (nct6775) Fix names of DIMM temperature sources hwmon: (k10temp) Support all Family 15h Model 6xh and Model 7xh processors scsi: arcmsr: clean up clang warning on extraneous parentheses pinctrl: gemini: Fix up TVC clock group orangefs: rate limit the client not running info message x86/mm: Do not warn about PCI BIOS W+X mappings ARM: 8802/1: Call syscall_trace_exit even when system call skipped spi: spidev: Fix OF tree warning logic pinctrl: gemini: Mask and set properly spi: fsl-lpspi: Prevent FIFO under/overrun by default gpio: syscon: Fix possible NULL ptr usage net: fix generic XDP to handle if eth header was mangled bpf: btf: Fix a missing check bug x86/kexec: Correct KEXEC_BACKUP_SRC_END off-by-one error lightnvm: pblk: consider max hw sectors supported for max_write_pgs lightnvm: pblk: fix error handling of pblk_lines_init() lightnvm: do no update csecs and sos on 1.2 lightnvm: pblk: guarantee mw_cunits on read buffer lightnvm: pblk: fix write amplificiation calculation lightnvm: pblk: guarantee emeta on line close lightnvm: pblk: fix incorrect min_write_pgs lightnvm: pblk: fix rqd.error return value in pblk_blk_erase_sync ALSA: hda/ca0132 - Fix input effect controls for desktop cards media: venus: vdec: fix decoded data size media: cx231xx: fix potential sign-extension overflow on large shift GFS2: Flush the GFS2 delete workqueue before stopping the kernel threads media: isif: fix a NULL pointer dereference bug printk: Give error on attempt to set log buffer length to over 2G mfd: ti_am335x_tscadc: Keep ADC interface on if child is wakeup capable backlight: lm3639: Unconditionally call led_classdev_unregister proc/vmcore: Fix i386 build error of missing copy_oldmem_page_encrypted() s390/kasan: avoid user access code instrumentation s390/kasan: avoid instrumentation of early C code s390/kasan: avoid vdso instrumentation mmc: mmci: expand startbiterr to irqmask and error check x86/intel_rdt: CBM overlap should also check for overlap with CDP peer x86/intel_rdt: Introduce utility to obtain CDP peer mtd: devices: m25p80: Make sure WRITE_EN is issued before each write mtd: spi-nor: cadence-quadspi: Use proper enum for dma_[un]map_single media: cx18: Don't check for address of video_dev media: dw9807-vcm: Fix probe error handling media: dw9714: Fix error handling in probe function platform/x86: mlx-platform: Properly use mlxplat_mlxcpld_msn201x_items bcache: recal cached_dev_sectors on detach bcache: account size of buckets used in uuid write to ca->meta_sectors_written reset: Fix potential use-after-free in __of_reset_control_get() fbdev: fix broken menu dependencies fbdev: sbuslib: integer overflow in sbusfb_ioctl_helper() fbdev: sbuslib: use checked version of put_user() atmel_lcdfb: support native-mode display-timings mmc: renesas_sdhi_internal_dmac: set scatter/gather max segment size mmc: tmio: Fix SCC error detection mmc: renesas_sdhi_internal_dmac: Whitelist r8a774a1 x86/fsgsbase/64: Fix ptrace() to read the FS/GS base accurately xsk: proper AF_XDP socket teardown ordering iwlwifi: mvm: don't send keys when entering D3 ACPI / SBS: Fix rare oops when removing modules xfrm: use correct size to initialise sp->ovec crypto: mxs-dcp - Fix AES issues crypto: mxs-dcp - Fix SHA null hashes and output length dmaengine: rcar-dmac: set scatter/gather max segment size x86/olpc: Fix build error with CONFIG_MFD_CS5535=m kexec: Allocate decrypted control pages for kdump if SME is enabled remoteproc: qcom: q6v5: Fix a race condition on fatal crash remoteproc: Check for NULL firmwares in sysfs interface tc-testing: fix build of eBPF programs net: hns3: Fix for rx vlan id handle to support Rev 0x21 hardware soc: fsl: bman_portals: defer probe after bman's probe Input: silead - try firmware reload after unsuccessful resume Input: st1232 - set INPUT_PROP_DIRECT property i2c: zx2967: use core to detect 'no zero length' quirk i2c: tegra: use core to detect 'no zero length' quirk i2c: qup: use core to detect 'no zero length' quirk i2c: omap: use core to detect 'no zero length' quirk gfs2: slow the deluge of io error messages media: cec-gpio: select correct Signal Free Time media: ov5640: fix framerate update dmaengine: ioat: fix prototype of ioat_enumerate_channels NFSv4.x: fix lock recovery during delegation recall printk: Correct wrong casting i2c: brcmstb: Allow enabling the driver on DSL SoCs clk: samsung: Use clk_hw API for calling clk framework from clk notifiers clk: samsung: exynos5420: Define CLK_SECKEY gate clock only or Exynos5420 clk: samsung: Use NOIRQ stage for Exynos5433 clocks suspend/resume qtnfmac: drop error reports for out-of-bounds key indexes qtnfmac: inform wireless core about supported extended capabilities qtnfmac: pass sgi rate info flag to wireless core qtnfmac: request userspace to do OBSS scanning if FW can not brcmfmac: fix full timeout waiting for action frame on-channel tx brcmfmac: reduce timeout for action frame scan cpu/SMT: State SMT is disabled even with nosmt and without "=force" mtd: physmap_of: Release resources on error usb: dwc2: disable power_down on rockchip devices USB: serial: cypress_m8: fix interrupt-out transfer length KVM: PPC: Book3S PR: Exiting split hack mode needs to fixup both PC and LR bnxt_en: return proper error when FW returns HWRM_ERR_CODE_RESOURCE_ACCESS_DENIED ALSA: hda/sigmatel - Disable automute for Elo VuPoint media: i2c: adv748x: Support probing a single output media: rcar-vin: fix redeclaration of symbol media: pxa_camera: Fix check for pdev->dev.of_node media: rc: ir-rc6-decoder: enable toggle bit for Kathrein RCU-676 remote qed: Avoid implicit enum conversion in qed_ooo_submit_tx_buffers ata: ep93xx: Use proper enums for directions powerpc/64s/radix: Explicitly flush ERAT with local LPID invalidation powerpc/time: Use clockevents_register_device(), fixing an issue with large decrementer ASoC: qdsp6: q6asm-dai: checking NULL vs IS_ERR() cpuidle: menu: Fix wakeup statistics updates for polling state ACPICA: Never run _REG on system_memory and system_IO OPP: Return error on error from dev_pm_opp_get_opp_count() msm/gpu/a6xx: Force of_dma_configure to setup DMA for GMU rpmsg: glink: smem: Support rx peak for size less than 4 bytes IB/mlx4: Avoid implicit enumerated type conversion RDMA/hns: Limit the size of extend sge of sq RDMA/hns: Bugfix for CM test RDMA/hns: Submit bad wr when post send wr exception RDMA/hns: Bugfix for reserved qp number IB/rxe: avoid srq memory leak IB/mthca: Fix error return code in __mthca_init_one() ixgbe: Fix crash with VFs and flow director on interface flap i40e: Use proper enum in i40e_ndo_set_vf_link_state ixgbe: Fix ixgbe TX hangs with XDP_TX beyond queue limit md: allow metadata updates while suspending an array - fix ice: Fix forward to queue group logic clocksource/drivers/sh_cmt: Fix clocksource width for 32-bit machines clocksource/drivers/sh_cmt: Fixup for 64-bit machines tools: PCI: Fix compilation warnings PM / hibernate: Check the success of generating md5 digest before hibernation mtd: rawnand: sh_flctl: Use proper enum for flctl_dma_fifo0_transfer ARM: dts: at91: sama5d2_ptc_ek: fix bootloader env offsets ARM: dts: at91: at91sam9x5cm: fix addressable nand flash size ARM: dts: at91: sama5d4_xplained: fix addressable nand flash size powerpc/xive: Move a dereference below a NULL test powerpc/pseries: Fix how we iterate over the DTL entries powerpc/pseries: Fix DTL buffer registration cxgb4: Use proper enum in IEEE_FAUX_SYNC cxgb4: Use proper enum in cxgb4_dcb_handle_fw_update mei: samples: fix a signedness bug in amt_host_if_call() x86/PCI: Apply VMD's AERSID fixup generically sunrpc: Fix connect metrics clk: keystone: Enable TISCI clocks if K3_ARCH ext4: fix build error when DX_DEBUG is defined ALSA: hda: Fix mismatch for register mask and value in ext controller. dmaengine: timb_dma: Use proper enum in td_prep_slave_sg dmaengine: ep93xx: Return proper enum in ep93xx_dma_chan_direction printk: CON_PRINTBUFFER console registration is a bit racy printk: Do not miss new messages when replaying the log KVM: PPC: Inform the userspace about TCE update failures watchdog: w83627hf_wdt: Support NCT6796D, NCT6797D, NCT6798D watchdog: sama5d4: fix timeout-sec usage watchdog: renesas_wdt: stop when unregistering watchdog: core: fix null pointer dereference when releasing cdev irqchip/irq-mvebu-icu: Fix wrong private data retrieval nl80211: Fix a GET_KEY reply attribute usb: dwc3: gadget: Check ENBLSLPM before sending ep command usb: gadget: udc: fotg210-udc: Fix a sleep-in-atomic-context bug in fotg210_get_status() selftests/tls: Fix recv(MSG_PEEK) & splice() test cases ath9k: fix reporting calculated new FFT upper max PM / devfreq: stopping the governor before device_unregister() PM / devfreq: Fix handling of min/max_freq == 0 PM / devfreq: Fix devfreq_add_device() when drivers are built as modules. ata: ahci_brcm: Allow using driver or DSL SoCs rtlwifi: btcoex: Use proper enumerated types for Wi-Fi only interface ath10k: fix vdev-start timeout on error arm64/numa: Report correct memblock range for the dummy node kvm: arm/arm64: Fix stage2_flush_memslot for 4 level page table iommu/arm-smmu-v3: Fix unexpected CMD_SYNC timeout iommu/io-pgtable-arm: Fix race handling in split_blk_unmap() mt76: fix handling ps-poll frames mt76x2: disable WLAN core before probe mt76x2: fix tx power configuration for VHT mcs 9 IB/hfi1: Ensure ucast_dlid access doesnt exceed bounds IB/hfi1: Error path MAD response size is incorrect f2fs: keep lazytime on remount ACPI / LPSS: Resume BYT/CHT I2C controllers from resume_noirq ACPI / LPSS: Make acpi_lpss_find_device() also find PCI devices SUNRPC: Fix priority queue fairness tcp: up initial rmem to 128KB and SYN rwin to around 64KB ARM: dts: sun8i: h3: bpi-m2-plus: Fix address for external RGMII Ethernet PHY ARM: dts: sun8i: h3-h5: ir register size should be the whole memory block f2fs: return correct errno in f2fs_gc net: hns3: Fix loss of coal configuration while doing reset net: hns3: Fix for netdev not up problem when setting mtu ARM: dts: omap5: enable OTG role for DWC3 controller ARM: dts: dra7: Enable workaround for errata i870 in PCIe host mode net: xen-netback: fix return type of ndo_start_xmit function net: ovs: fix return type of ndo_start_xmit function bpf, x32: Fix bug for BPF_JMP | {BPF_JSGT, BPF_JSLE, BPF_JSLT, BPF_JSGE} bpf, x32: Fix bug with ALU64 {LSH, RSH, ARSH} BPF_K shift by 0 bpf, x32: Fix bug with ALU64 {LSH, RSH, ARSH} BPF_X shift by 0 bpf, x32: Fix bug for BPF_ALU64 | BPF_NEG fbdev: Ditch fb_edid_add_monspecs arm64: uaccess: Ensure PAN is re-enabled after unhandled uaccess fault mm/memory_hotplug: fix updating the node span mm/memory_hotplug: don't access uninitialized memmaps in shrink_pgdat_span() idr: Fix idr_get_next race with idr_remove net: cdc_ncm: Signedness bug in cdc_ncm_set_dgram_size() Revert "OPP: Protect dev_list with opp_table lock" tee: optee: add missing of_node_put after of_device_is_available i2c: mediatek: modify threshold passed to i2c_get_dma_safe_msg_buf() spi: mediatek: use correct mata->xfer_len when in fifo transfer Conflicts: drivers/rpmsg/qcom_glink_smem.c drivers/usb/dwc3/gadget.c Change-Id: I6e0f156d860bf2afcaabcf70d653676eb7d3de4e Signed-off-by: Ivaylo Georgiev <irgeorgiev@codeaurora.org>
610 lines
19 KiB
C
610 lines
19 KiB
C
/*
|
|
* menu.c - the menu idle governor
|
|
*
|
|
* Copyright (C) 2006-2007 Adam Belay <abelay@novell.com>
|
|
* Copyright (C) 2009 Intel Corporation
|
|
* Author:
|
|
* Arjan van de Ven <arjan@linux.intel.com>
|
|
*
|
|
* This code is licenced under the GPL version 2 as described
|
|
* in the COPYING file that acompanies the Linux Kernel.
|
|
*/
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/cpuidle.h>
|
|
#include <linux/time.h>
|
|
#include <linux/ktime.h>
|
|
#include <linux/hrtimer.h>
|
|
#include <linux/tick.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/sched/loadavg.h>
|
|
#include <linux/sched/stat.h>
|
|
#include <linux/math64.h>
|
|
|
|
/*
|
|
* Please note when changing the tuning values:
|
|
* If (MAX_INTERESTING-1) * RESOLUTION > UINT_MAX, the result of
|
|
* a scaling operation multiplication may overflow on 32 bit platforms.
|
|
* In that case, #define RESOLUTION as ULL to get 64 bit result:
|
|
* #define RESOLUTION 1024ULL
|
|
*
|
|
* The default values do not overflow.
|
|
*/
|
|
#define BUCKETS 12
|
|
#define INTERVAL_SHIFT 3
|
|
#define INTERVALS (1UL << INTERVAL_SHIFT)
|
|
#define RESOLUTION 1024
|
|
#define DECAY 8
|
|
#define MAX_INTERESTING 50000
|
|
|
|
|
|
/*
|
|
* Concepts and ideas behind the menu governor
|
|
*
|
|
* For the menu governor, there are 3 decision factors for picking a C
|
|
* state:
|
|
* 1) Energy break even point
|
|
* 2) Performance impact
|
|
* 3) Latency tolerance (from pmqos infrastructure)
|
|
* These these three factors are treated independently.
|
|
*
|
|
* Energy break even point
|
|
* -----------------------
|
|
* C state entry and exit have an energy cost, and a certain amount of time in
|
|
* the C state is required to actually break even on this cost. CPUIDLE
|
|
* provides us this duration in the "target_residency" field. So all that we
|
|
* need is a good prediction of how long we'll be idle. Like the traditional
|
|
* menu governor, we start with the actual known "next timer event" time.
|
|
*
|
|
* Since there are other source of wakeups (interrupts for example) than
|
|
* the next timer event, this estimation is rather optimistic. To get a
|
|
* more realistic estimate, a correction factor is applied to the estimate,
|
|
* that is based on historic behavior. For example, if in the past the actual
|
|
* duration always was 50% of the next timer tick, the correction factor will
|
|
* be 0.5.
|
|
*
|
|
* menu uses a running average for this correction factor, however it uses a
|
|
* set of factors, not just a single factor. This stems from the realization
|
|
* that the ratio is dependent on the order of magnitude of the expected
|
|
* duration; if we expect 500 milliseconds of idle time the likelihood of
|
|
* getting an interrupt very early is much higher than if we expect 50 micro
|
|
* seconds of idle time. A second independent factor that has big impact on
|
|
* the actual factor is if there is (disk) IO outstanding or not.
|
|
* (as a special twist, we consider every sleep longer than 50 milliseconds
|
|
* as perfect; there are no power gains for sleeping longer than this)
|
|
*
|
|
* For these two reasons we keep an array of 12 independent factors, that gets
|
|
* indexed based on the magnitude of the expected duration as well as the
|
|
* "is IO outstanding" property.
|
|
*
|
|
* Repeatable-interval-detector
|
|
* ----------------------------
|
|
* There are some cases where "next timer" is a completely unusable predictor:
|
|
* Those cases where the interval is fixed, for example due to hardware
|
|
* interrupt mitigation, but also due to fixed transfer rate devices such as
|
|
* mice.
|
|
* For this, we use a different predictor: We track the duration of the last 8
|
|
* intervals and if the stand deviation of these 8 intervals is below a
|
|
* threshold value, we use the average of these intervals as prediction.
|
|
*
|
|
* Limiting Performance Impact
|
|
* ---------------------------
|
|
* C states, especially those with large exit latencies, can have a real
|
|
* noticeable impact on workloads, which is not acceptable for most sysadmins,
|
|
* and in addition, less performance has a power price of its own.
|
|
*
|
|
* As a general rule of thumb, menu assumes that the following heuristic
|
|
* holds:
|
|
* The busier the system, the less impact of C states is acceptable
|
|
*
|
|
* This rule-of-thumb is implemented using a performance-multiplier:
|
|
* If the exit latency times the performance multiplier is longer than
|
|
* the predicted duration, the C state is not considered a candidate
|
|
* for selection due to a too high performance impact. So the higher
|
|
* this multiplier is, the longer we need to be idle to pick a deep C
|
|
* state, and thus the less likely a busy CPU will hit such a deep
|
|
* C state.
|
|
*
|
|
* Two factors are used in determing this multiplier:
|
|
* a value of 10 is added for each point of "per cpu load average" we have.
|
|
* a value of 5 points is added for each process that is waiting for
|
|
* IO on this CPU.
|
|
* (these values are experimentally determined)
|
|
*
|
|
* The load average factor gives a longer term (few seconds) input to the
|
|
* decision, while the iowait value gives a cpu local instantanious input.
|
|
* The iowait factor may look low, but realize that this is also already
|
|
* represented in the system load average.
|
|
*
|
|
*/
|
|
|
|
struct menu_device {
|
|
int last_state_idx;
|
|
int needs_update;
|
|
int tick_wakeup;
|
|
|
|
unsigned int next_timer_us;
|
|
unsigned int predicted_us;
|
|
unsigned int bucket;
|
|
unsigned int correction_factor[BUCKETS];
|
|
unsigned int intervals[INTERVALS];
|
|
int interval_ptr;
|
|
};
|
|
|
|
static inline int get_loadavg(unsigned long load)
|
|
{
|
|
return LOAD_INT(load) * 10 + LOAD_FRAC(load) / 10;
|
|
}
|
|
|
|
static inline int which_bucket(unsigned int duration, unsigned long nr_iowaiters)
|
|
{
|
|
int bucket = 0;
|
|
|
|
/*
|
|
* We keep two groups of stats; one with no
|
|
* IO pending, one without.
|
|
* This allows us to calculate
|
|
* E(duration)|iowait
|
|
*/
|
|
if (nr_iowaiters)
|
|
bucket = BUCKETS/2;
|
|
|
|
if (duration < 10)
|
|
return bucket;
|
|
if (duration < 100)
|
|
return bucket + 1;
|
|
if (duration < 1000)
|
|
return bucket + 2;
|
|
if (duration < 10000)
|
|
return bucket + 3;
|
|
if (duration < 100000)
|
|
return bucket + 4;
|
|
return bucket + 5;
|
|
}
|
|
|
|
/*
|
|
* Return a multiplier for the exit latency that is intended
|
|
* to take performance requirements into account.
|
|
* The more performance critical we estimate the system
|
|
* to be, the higher this multiplier, and thus the higher
|
|
* the barrier to go to an expensive C state.
|
|
*/
|
|
static inline int performance_multiplier(unsigned long nr_iowaiters, unsigned long load)
|
|
{
|
|
int mult = 1;
|
|
|
|
/* for higher loadavg, we are more reluctant */
|
|
|
|
/*
|
|
* this doesn't work as intended - it is almost always 0, but can
|
|
* sometimes, depending on workload, spike very high into the hundreds
|
|
* even when the average cpu load is under 10%.
|
|
*/
|
|
/* mult += 2 * get_loadavg(); */
|
|
|
|
/* for IO wait tasks (per cpu!) we add 5x each */
|
|
mult += 10 * nr_iowaiters;
|
|
|
|
return mult;
|
|
}
|
|
|
|
static DEFINE_PER_CPU(struct menu_device, menu_devices);
|
|
|
|
static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev);
|
|
|
|
/*
|
|
* Try detecting repeating patterns by keeping track of the last 8
|
|
* intervals, and checking if the standard deviation of that set
|
|
* of points is below a threshold. If it is... then use the
|
|
* average of these 8 points as the estimated value.
|
|
*/
|
|
static unsigned int get_typical_interval(struct menu_device *data)
|
|
{
|
|
int i, divisor;
|
|
unsigned int max, thresh, avg;
|
|
uint64_t sum, variance;
|
|
|
|
thresh = UINT_MAX; /* Discard outliers above this value */
|
|
|
|
again:
|
|
|
|
/* First calculate the average of past intervals */
|
|
max = 0;
|
|
sum = 0;
|
|
divisor = 0;
|
|
for (i = 0; i < INTERVALS; i++) {
|
|
unsigned int value = data->intervals[i];
|
|
if (value <= thresh) {
|
|
sum += value;
|
|
divisor++;
|
|
if (value > max)
|
|
max = value;
|
|
}
|
|
}
|
|
if (divisor == INTERVALS)
|
|
avg = sum >> INTERVAL_SHIFT;
|
|
else
|
|
avg = div_u64(sum, divisor);
|
|
|
|
/* Then try to determine variance */
|
|
variance = 0;
|
|
for (i = 0; i < INTERVALS; i++) {
|
|
unsigned int value = data->intervals[i];
|
|
if (value <= thresh) {
|
|
int64_t diff = (int64_t)value - avg;
|
|
variance += diff * diff;
|
|
}
|
|
}
|
|
if (divisor == INTERVALS)
|
|
variance >>= INTERVAL_SHIFT;
|
|
else
|
|
do_div(variance, divisor);
|
|
|
|
/*
|
|
* The typical interval is obtained when standard deviation is
|
|
* small (stddev <= 20 us, variance <= 400 us^2) or standard
|
|
* deviation is small compared to the average interval (avg >
|
|
* 6*stddev, avg^2 > 36*variance). The average is smaller than
|
|
* UINT_MAX aka U32_MAX, so computing its square does not
|
|
* overflow a u64. We simply reject this candidate average if
|
|
* the standard deviation is greater than 715 s (which is
|
|
* rather unlikely).
|
|
*
|
|
* Use this result only if there is no timer to wake us up sooner.
|
|
*/
|
|
if (likely(variance <= U64_MAX/36)) {
|
|
if ((((u64)avg*avg > variance*36) && (divisor * 4 >= INTERVALS * 3))
|
|
|| variance <= 400) {
|
|
return avg;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* If we have outliers to the upside in our distribution, discard
|
|
* those by setting the threshold to exclude these outliers, then
|
|
* calculate the average and standard deviation again. Once we get
|
|
* down to the bottom 3/4 of our samples, stop excluding samples.
|
|
*
|
|
* This can deal with workloads that have long pauses interspersed
|
|
* with sporadic activity with a bunch of short pauses.
|
|
*/
|
|
if ((divisor * 4) <= INTERVALS * 3)
|
|
return UINT_MAX;
|
|
|
|
thresh = max - 1;
|
|
goto again;
|
|
}
|
|
|
|
/**
|
|
* menu_select - selects the next idle state to enter
|
|
* @drv: cpuidle driver containing state data
|
|
* @dev: the CPU
|
|
* @stop_tick: indication on whether or not to stop the tick
|
|
*/
|
|
static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
|
|
bool *stop_tick)
|
|
{
|
|
struct menu_device *data = this_cpu_ptr(&menu_devices);
|
|
int latency_req = cpuidle_governor_latency_req(dev->cpu);
|
|
int i;
|
|
int first_idx;
|
|
int idx;
|
|
unsigned int interactivity_req;
|
|
unsigned int expected_interval;
|
|
unsigned long nr_iowaiters, cpu_load;
|
|
ktime_t delta_next;
|
|
|
|
if (data->needs_update) {
|
|
menu_update(drv, dev);
|
|
data->needs_update = 0;
|
|
}
|
|
|
|
/* Special case when user has set very strict latency requirement */
|
|
if (unlikely(latency_req == 0)) {
|
|
*stop_tick = false;
|
|
return 0;
|
|
}
|
|
|
|
/* determine the expected residency time, round up */
|
|
data->next_timer_us = ktime_to_us(tick_nohz_get_sleep_length(&delta_next));
|
|
|
|
get_iowait_load(&nr_iowaiters, &cpu_load);
|
|
data->bucket = which_bucket(data->next_timer_us, nr_iowaiters);
|
|
|
|
/*
|
|
* Force the result of multiplication to be 64 bits even if both
|
|
* operands are 32 bits.
|
|
* Make sure to round up for half microseconds.
|
|
*/
|
|
data->predicted_us = DIV_ROUND_CLOSEST_ULL((uint64_t)data->next_timer_us *
|
|
data->correction_factor[data->bucket],
|
|
RESOLUTION * DECAY);
|
|
|
|
expected_interval = get_typical_interval(data);
|
|
expected_interval = min(expected_interval, data->next_timer_us);
|
|
|
|
first_idx = 0;
|
|
if (drv->states[0].flags & CPUIDLE_FLAG_POLLING) {
|
|
struct cpuidle_state *s = &drv->states[1];
|
|
unsigned int polling_threshold;
|
|
|
|
/*
|
|
* Default to a physical idle state, not to busy polling, unless
|
|
* a timer is going to trigger really really soon.
|
|
*/
|
|
polling_threshold = max_t(unsigned int, 20, s->target_residency);
|
|
if (data->next_timer_us > polling_threshold &&
|
|
latency_req > s->exit_latency && !s->disabled &&
|
|
!dev->states_usage[1].disable)
|
|
first_idx = 1;
|
|
}
|
|
|
|
/*
|
|
* Use the lowest expected idle interval to pick the idle state.
|
|
*/
|
|
data->predicted_us = min(data->predicted_us, expected_interval);
|
|
|
|
if (tick_nohz_tick_stopped()) {
|
|
/*
|
|
* If the tick is already stopped, the cost of possible short
|
|
* idle duration misprediction is much higher, because the CPU
|
|
* may be stuck in a shallow idle state for a long time as a
|
|
* result of it. In that case say we might mispredict and use
|
|
* the known time till the closest timer event for the idle
|
|
* state selection.
|
|
*/
|
|
if (data->predicted_us < TICK_USEC)
|
|
data->predicted_us = ktime_to_us(delta_next);
|
|
} else {
|
|
/*
|
|
* Use the performance multiplier and the user-configurable
|
|
* latency_req to determine the maximum exit latency.
|
|
*/
|
|
interactivity_req = data->predicted_us / performance_multiplier(nr_iowaiters, cpu_load);
|
|
if (latency_req > interactivity_req)
|
|
latency_req = interactivity_req;
|
|
}
|
|
|
|
expected_interval = data->predicted_us;
|
|
/*
|
|
* Find the idle state with the lowest power while satisfying
|
|
* our constraints.
|
|
*/
|
|
idx = -1;
|
|
for (i = first_idx; i < drv->state_count; i++) {
|
|
struct cpuidle_state *s = &drv->states[i];
|
|
struct cpuidle_state_usage *su = &dev->states_usage[i];
|
|
|
|
if (s->disabled || su->disable)
|
|
continue;
|
|
if (idx == -1)
|
|
idx = i; /* first enabled state */
|
|
if (s->target_residency > data->predicted_us) {
|
|
if (data->predicted_us < TICK_USEC)
|
|
break;
|
|
|
|
if (!tick_nohz_tick_stopped()) {
|
|
/*
|
|
* If the state selected so far is shallow,
|
|
* waking up early won't hurt, so retain the
|
|
* tick in that case and let the governor run
|
|
* again in the next iteration of the loop.
|
|
*/
|
|
expected_interval = drv->states[idx].target_residency;
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* If the state selected so far is shallow and this
|
|
* state's target residency matches the time till the
|
|
* closest timer event, select this one to avoid getting
|
|
* stuck in the shallow one for too long.
|
|
*/
|
|
if (drv->states[idx].target_residency < TICK_USEC &&
|
|
s->target_residency <= ktime_to_us(delta_next))
|
|
idx = i;
|
|
|
|
goto out;
|
|
}
|
|
if (s->exit_latency > latency_req) {
|
|
/*
|
|
* If we break out of the loop for latency reasons, use
|
|
* the target residency of the selected state as the
|
|
* expected idle duration so that the tick is retained
|
|
* as long as that target residency is low enough.
|
|
*/
|
|
expected_interval = drv->states[idx].target_residency;
|
|
break;
|
|
}
|
|
idx = i;
|
|
}
|
|
|
|
if (idx == -1)
|
|
idx = 0; /* No states enabled. Must use 0. */
|
|
|
|
/*
|
|
* Don't stop the tick if the selected state is a polling one or if the
|
|
* expected idle duration is shorter than the tick period length.
|
|
*/
|
|
if (((drv->states[idx].flags & CPUIDLE_FLAG_POLLING) ||
|
|
expected_interval < TICK_USEC) && !tick_nohz_tick_stopped()) {
|
|
unsigned int delta_next_us = ktime_to_us(delta_next);
|
|
|
|
*stop_tick = false;
|
|
|
|
if (idx > 0 && drv->states[idx].target_residency > delta_next_us) {
|
|
/*
|
|
* The tick is not going to be stopped and the target
|
|
* residency of the state to be returned is not within
|
|
* the time until the next timer event including the
|
|
* tick, so try to correct that.
|
|
*/
|
|
for (i = idx - 1; i >= 0; i--) {
|
|
if (drv->states[i].disabled ||
|
|
dev->states_usage[i].disable)
|
|
continue;
|
|
|
|
idx = i;
|
|
if (drv->states[i].target_residency <= delta_next_us)
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
out:
|
|
data->last_state_idx = idx;
|
|
|
|
return data->last_state_idx;
|
|
}
|
|
|
|
/**
|
|
* menu_reflect - records that data structures need update
|
|
* @dev: the CPU
|
|
* @index: the index of actual entered state
|
|
*
|
|
* NOTE: it's important to be fast here because this operation will add to
|
|
* the overall exit latency.
|
|
*/
|
|
static void menu_reflect(struct cpuidle_device *dev, int index)
|
|
{
|
|
struct menu_device *data = this_cpu_ptr(&menu_devices);
|
|
|
|
data->last_state_idx = index;
|
|
data->needs_update = 1;
|
|
data->tick_wakeup = tick_nohz_idle_got_tick();
|
|
}
|
|
|
|
/**
|
|
* menu_update - attempts to guess what happened after entry
|
|
* @drv: cpuidle driver containing state data
|
|
* @dev: the CPU
|
|
*/
|
|
static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev)
|
|
{
|
|
struct menu_device *data = this_cpu_ptr(&menu_devices);
|
|
int last_idx = data->last_state_idx;
|
|
struct cpuidle_state *target = &drv->states[last_idx];
|
|
unsigned int measured_us;
|
|
unsigned int new_factor;
|
|
|
|
/*
|
|
* Try to figure out how much time passed between entry to low
|
|
* power state and occurrence of the wakeup event.
|
|
*
|
|
* If the entered idle state didn't support residency measurements,
|
|
* we use them anyway if they are short, and if long,
|
|
* truncate to the whole expected time.
|
|
*
|
|
* Any measured amount of time will include the exit latency.
|
|
* Since we are interested in when the wakeup begun, not when it
|
|
* was completed, we must subtract the exit latency. However, if
|
|
* the measured amount of time is less than the exit latency,
|
|
* assume the state was never reached and the exit latency is 0.
|
|
*/
|
|
|
|
if (data->tick_wakeup && data->next_timer_us > TICK_USEC) {
|
|
/*
|
|
* The nohz code said that there wouldn't be any events within
|
|
* the tick boundary (if the tick was stopped), but the idle
|
|
* duration predictor had a differing opinion. Since the CPU
|
|
* was woken up by a tick (that wasn't stopped after all), the
|
|
* predictor was not quite right, so assume that the CPU could
|
|
* have been idle long (but not forever) to help the idle
|
|
* duration predictor do a better job next time.
|
|
*/
|
|
measured_us = 9 * MAX_INTERESTING / 10;
|
|
} else if ((drv->states[last_idx].flags & CPUIDLE_FLAG_POLLING) &&
|
|
dev->poll_time_limit) {
|
|
/*
|
|
* The CPU exited the "polling" state due to a time limit, so
|
|
* the idle duration prediction leading to the selection of that
|
|
* state was inaccurate. If a better prediction had been made,
|
|
* the CPU might have been woken up from idle by the next timer.
|
|
* Assume that to be the case.
|
|
*/
|
|
measured_us = data->next_timer_us;
|
|
} else {
|
|
/* measured value */
|
|
measured_us = cpuidle_get_last_residency(dev);
|
|
|
|
/* Deduct exit latency */
|
|
if (measured_us > 2 * target->exit_latency)
|
|
measured_us -= target->exit_latency;
|
|
else
|
|
measured_us /= 2;
|
|
}
|
|
|
|
/* Make sure our coefficients do not exceed unity */
|
|
if (measured_us > data->next_timer_us)
|
|
measured_us = data->next_timer_us;
|
|
|
|
/* Update our correction ratio */
|
|
new_factor = data->correction_factor[data->bucket];
|
|
new_factor -= new_factor / DECAY;
|
|
|
|
if (data->next_timer_us > 0 && measured_us < MAX_INTERESTING)
|
|
new_factor += RESOLUTION * measured_us / data->next_timer_us;
|
|
else
|
|
/*
|
|
* we were idle so long that we count it as a perfect
|
|
* prediction
|
|
*/
|
|
new_factor += RESOLUTION;
|
|
|
|
/*
|
|
* We don't want 0 as factor; we always want at least
|
|
* a tiny bit of estimated time. Fortunately, due to rounding,
|
|
* new_factor will stay nonzero regardless of measured_us values
|
|
* and the compiler can eliminate this test as long as DECAY > 1.
|
|
*/
|
|
if (DECAY == 1 && unlikely(new_factor == 0))
|
|
new_factor = 1;
|
|
|
|
data->correction_factor[data->bucket] = new_factor;
|
|
|
|
/* update the repeating-pattern data */
|
|
data->intervals[data->interval_ptr++] = measured_us;
|
|
if (data->interval_ptr >= INTERVALS)
|
|
data->interval_ptr = 0;
|
|
}
|
|
|
|
/**
|
|
* menu_enable_device - scans a CPU's states and does setup
|
|
* @drv: cpuidle driver
|
|
* @dev: the CPU
|
|
*/
|
|
static int menu_enable_device(struct cpuidle_driver *drv,
|
|
struct cpuidle_device *dev)
|
|
{
|
|
struct menu_device *data = &per_cpu(menu_devices, dev->cpu);
|
|
int i;
|
|
|
|
memset(data, 0, sizeof(struct menu_device));
|
|
|
|
/*
|
|
* if the correction factor is 0 (eg first time init or cpu hotplug
|
|
* etc), we actually want to start out with a unity factor.
|
|
*/
|
|
for(i = 0; i < BUCKETS; i++)
|
|
data->correction_factor[i] = RESOLUTION * DECAY;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static struct cpuidle_governor menu_governor = {
|
|
.name = "menu",
|
|
.rating = 20,
|
|
.enable = menu_enable_device,
|
|
.select = menu_select,
|
|
.reflect = menu_reflect,
|
|
};
|
|
|
|
/**
|
|
* init_menu - initializes the governor
|
|
*/
|
|
static int __init init_menu(void)
|
|
{
|
|
return cpuidle_register_governor(&menu_governor);
|
|
}
|
|
|
|
postcore_initcall(init_menu);
|