Merge branch 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull core timer updates from Thomas Gleixner: "Timers and timekeeping updates: - A large overhaul of the posix CPU timer code which is a preparation for moving the CPU timer expiry out into task work so it can be properly accounted on the task/process. An update to the bogus permission checks will come later during the merge window as feedback was not complete before heading of for travel. - Switch the timerqueue code to use cached rbtrees and get rid of the homebrewn caching of the leftmost node. - Consolidate hrtimer_init() + hrtimer_init_sleeper() calls into a single function - Implement the separation of hrtimers to be forced to expire in hard interrupt context even when PREEMPT_RT is enabled and mark the affected timers accordingly. - Implement a mechanism for hrtimers and the timer wheel to protect RT against priority inversion and live lock issues when a (hr)timer which should be canceled is currently executing the callback. Instead of infinitely spinning, the task which tries to cancel the timer blocks on a per cpu base expiry lock which is held and released by the (hr)timer expiry code. - Enable the Hyper-V TSC page based sched_clock for Hyper-V guests resulting in faster access to timekeeping functions. - Updates to various clocksource/clockevent drivers and their device tree bindings. - The usual small improvements all over the place" * 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (101 commits) posix-cpu-timers: Fix permission check regression posix-cpu-timers: Always clear head pointer on dequeue hrtimer: Add a missing bracket and hide `migration_base' on !SMP posix-cpu-timers: Make expiry_active check actually work correctly posix-timers: Unbreak CONFIG_POSIX_TIMERS=n build tick: Mark sched_timer to expire in hard interrupt context hrtimer: Add kernel doc annotation for HRTIMER_MODE_HARD x86/hyperv: Hide pv_ops access for CONFIG_PARAVIRT=n posix-cpu-timers: Utilize timerqueue for storage posix-cpu-timers: Move state tracking to struct posix_cputimers posix-cpu-timers: Deduplicate rlimit handling posix-cpu-timers: Remove pointless comparisons posix-cpu-timers: Get rid of 64bit divisions posix-cpu-timers: Consolidate timer expiry further posix-cpu-timers: Get rid of zero checks rlimit: Rewrite non-sensical RLIMIT_CPU comment posix-cpu-timers: Respect INFINITY for hard RTTIME limit posix-cpu-timers: Switch thread group sampling to array posix-cpu-timers: Restructure expiry array posix-cpu-timers: Remove cputime_expires ...
This commit is contained in:
@@ -429,7 +429,7 @@ config ATMEL_ST
|
||||
|
||||
config ATMEL_TCB_CLKSRC
|
||||
bool "Atmel TC Block timer driver" if COMPILE_TEST
|
||||
depends on HAS_IOMEM
|
||||
depends on ARM && HAS_IOMEM
|
||||
select TIMER_OF if OF
|
||||
help
|
||||
Support for Timer Counter Blocks on Atmel SoCs.
|
||||
|
@@ -291,10 +291,8 @@ static int em_sti_probe(struct platform_device *pdev)
|
||||
platform_set_drvdata(pdev, p);
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0) {
|
||||
dev_err(&pdev->dev, "failed to get irq\n");
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
}
|
||||
|
||||
/* map memory, let base point to the STI instance */
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
|
@@ -22,6 +22,7 @@
|
||||
#include <asm/mshyperv.h>
|
||||
|
||||
static struct clock_event_device __percpu *hv_clock_event;
|
||||
static u64 hv_sched_clock_offset __ro_after_init;
|
||||
|
||||
/*
|
||||
* If false, we're using the old mechanism for stimer0 interrupts
|
||||
@@ -212,19 +213,17 @@ EXPORT_SYMBOL_GPL(hv_stimer_global_cleanup);
|
||||
struct clocksource *hyperv_cs;
|
||||
EXPORT_SYMBOL_GPL(hyperv_cs);
|
||||
|
||||
#ifdef CONFIG_HYPERV_TSCPAGE
|
||||
|
||||
static struct ms_hyperv_tsc_page *tsc_pg;
|
||||
static struct ms_hyperv_tsc_page tsc_pg __aligned(PAGE_SIZE);
|
||||
|
||||
struct ms_hyperv_tsc_page *hv_get_tsc_page(void)
|
||||
{
|
||||
return tsc_pg;
|
||||
return &tsc_pg;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hv_get_tsc_page);
|
||||
|
||||
static u64 notrace read_hv_sched_clock_tsc(void)
|
||||
static u64 notrace read_hv_clock_tsc(struct clocksource *arg)
|
||||
{
|
||||
u64 current_tick = hv_read_tsc_page(tsc_pg);
|
||||
u64 current_tick = hv_read_tsc_page(&tsc_pg);
|
||||
|
||||
if (current_tick == U64_MAX)
|
||||
hv_get_time_ref_count(current_tick);
|
||||
@@ -232,9 +231,9 @@ static u64 notrace read_hv_sched_clock_tsc(void)
|
||||
return current_tick;
|
||||
}
|
||||
|
||||
static u64 read_hv_clock_tsc(struct clocksource *arg)
|
||||
static u64 read_hv_sched_clock_tsc(void)
|
||||
{
|
||||
return read_hv_sched_clock_tsc();
|
||||
return read_hv_clock_tsc(NULL) - hv_sched_clock_offset;
|
||||
}
|
||||
|
||||
static struct clocksource hyperv_cs_tsc = {
|
||||
@@ -244,9 +243,8 @@ static struct clocksource hyperv_cs_tsc = {
|
||||
.mask = CLOCKSOURCE_MASK(64),
|
||||
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
||||
};
|
||||
#endif
|
||||
|
||||
static u64 notrace read_hv_sched_clock_msr(void)
|
||||
static u64 notrace read_hv_clock_msr(struct clocksource *arg)
|
||||
{
|
||||
u64 current_tick;
|
||||
/*
|
||||
@@ -258,9 +256,9 @@ static u64 notrace read_hv_sched_clock_msr(void)
|
||||
return current_tick;
|
||||
}
|
||||
|
||||
static u64 read_hv_clock_msr(struct clocksource *arg)
|
||||
static u64 read_hv_sched_clock_msr(void)
|
||||
{
|
||||
return read_hv_sched_clock_msr();
|
||||
return read_hv_clock_msr(NULL) - hv_sched_clock_offset;
|
||||
}
|
||||
|
||||
static struct clocksource hyperv_cs_msr = {
|
||||
@@ -271,7 +269,6 @@ static struct clocksource hyperv_cs_msr = {
|
||||
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_HYPERV_TSCPAGE
|
||||
static bool __init hv_init_tsc_clocksource(void)
|
||||
{
|
||||
u64 tsc_msr;
|
||||
@@ -280,12 +277,8 @@ static bool __init hv_init_tsc_clocksource(void)
|
||||
if (!(ms_hyperv.features & HV_MSR_REFERENCE_TSC_AVAILABLE))
|
||||
return false;
|
||||
|
||||
tsc_pg = vmalloc(PAGE_SIZE);
|
||||
if (!tsc_pg)
|
||||
return false;
|
||||
|
||||
hyperv_cs = &hyperv_cs_tsc;
|
||||
phys_addr = page_to_phys(vmalloc_to_page(tsc_pg));
|
||||
phys_addr = virt_to_phys(&tsc_pg);
|
||||
|
||||
/*
|
||||
* The Hyper-V TLFS specifies to preserve the value of reserved
|
||||
@@ -302,17 +295,11 @@ static bool __init hv_init_tsc_clocksource(void)
|
||||
hv_set_clocksource_vdso(hyperv_cs_tsc);
|
||||
clocksource_register_hz(&hyperv_cs_tsc, NSEC_PER_SEC/100);
|
||||
|
||||
/* sched_clock_register is needed on ARM64 but is a no-op on x86 */
|
||||
sched_clock_register(read_hv_sched_clock_tsc, 64, HV_CLOCK_HZ);
|
||||
hv_sched_clock_offset = hyperv_cs->read(hyperv_cs);
|
||||
hv_setup_sched_clock(read_hv_sched_clock_tsc);
|
||||
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
static bool __init hv_init_tsc_clocksource(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void __init hv_init_clocksource(void)
|
||||
{
|
||||
@@ -333,7 +320,7 @@ void __init hv_init_clocksource(void)
|
||||
hyperv_cs = &hyperv_cs_msr;
|
||||
clocksource_register_hz(&hyperv_cs_msr, NSEC_PER_SEC/100);
|
||||
|
||||
/* sched_clock_register is needed on ARM64 but is a no-op on x86 */
|
||||
sched_clock_register(read_hv_sched_clock_msr, 64, HV_CLOCK_HZ);
|
||||
hv_sched_clock_offset = hyperv_cs->read(hyperv_cs);
|
||||
hv_setup_sched_clock(read_hv_sched_clock_msr);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hv_init_clocksource);
|
||||
|
@@ -221,7 +221,7 @@ static int __init ostm_init(struct device_node *np)
|
||||
}
|
||||
|
||||
rate = clk_get_rate(ostm_clk);
|
||||
ostm->ticks_per_jiffy = (rate + HZ / 2) / HZ;
|
||||
ostm->ticks_per_jiffy = DIV_ROUND_CLOSEST(rate, HZ);
|
||||
|
||||
/*
|
||||
* First probed device will be used as system clocksource. Any
|
||||
|
@@ -776,11 +776,8 @@ static int sh_cmt_register_clockevent(struct sh_cmt_channel *ch,
|
||||
int ret;
|
||||
|
||||
irq = platform_get_irq(ch->cmt->pdev, ch->index);
|
||||
if (irq < 0) {
|
||||
dev_err(&ch->cmt->pdev->dev, "ch%u: failed to get irq\n",
|
||||
ch->index);
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
}
|
||||
|
||||
ret = request_irq(irq, sh_cmt_interrupt,
|
||||
IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING,
|
||||
@@ -921,12 +918,24 @@ static const struct platform_device_id sh_cmt_id_table[] = {
|
||||
MODULE_DEVICE_TABLE(platform, sh_cmt_id_table);
|
||||
|
||||
static const struct of_device_id sh_cmt_of_table[] __maybe_unused = {
|
||||
{ .compatible = "renesas,cmt-48", .data = &sh_cmt_info[SH_CMT_48BIT] },
|
||||
{
|
||||
/* deprecated, preserved for backward compatibility */
|
||||
.compatible = "renesas,cmt-48",
|
||||
.data = &sh_cmt_info[SH_CMT_48BIT]
|
||||
},
|
||||
{
|
||||
/* deprecated, preserved for backward compatibility */
|
||||
.compatible = "renesas,cmt-48-gen2",
|
||||
.data = &sh_cmt_info[SH_CMT0_RCAR_GEN2]
|
||||
},
|
||||
{
|
||||
.compatible = "renesas,r8a7740-cmt1",
|
||||
.data = &sh_cmt_info[SH_CMT_48BIT]
|
||||
},
|
||||
{
|
||||
.compatible = "renesas,sh73a0-cmt1",
|
||||
.data = &sh_cmt_info[SH_CMT_48BIT]
|
||||
},
|
||||
{
|
||||
.compatible = "renesas,rcar-gen2-cmt0",
|
||||
.data = &sh_cmt_info[SH_CMT0_RCAR_GEN2]
|
||||
|
@@ -462,11 +462,8 @@ static int sh_tmu_channel_setup(struct sh_tmu_channel *ch, unsigned int index,
|
||||
ch->base = tmu->mapbase + 8 + ch->index * 12;
|
||||
|
||||
ch->irq = platform_get_irq(tmu->pdev, index);
|
||||
if (ch->irq < 0) {
|
||||
dev_err(&tmu->pdev->dev, "ch%u: failed to get irq\n",
|
||||
ch->index);
|
||||
if (ch->irq < 0)
|
||||
return ch->irq;
|
||||
}
|
||||
|
||||
ch->cs_enabled = false;
|
||||
ch->enable_count = 0;
|
||||
|
@@ -6,6 +6,7 @@
|
||||
#include <linux/irq.h>
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/io.h>
|
||||
@@ -125,6 +126,18 @@ static u64 notrace tc_sched_clock_read32(void)
|
||||
return tc_get_cycles32(&clksrc);
|
||||
}
|
||||
|
||||
static struct delay_timer tc_delay_timer;
|
||||
|
||||
static unsigned long tc_delay_timer_read(void)
|
||||
{
|
||||
return tc_get_cycles(&clksrc);
|
||||
}
|
||||
|
||||
static unsigned long notrace tc_delay_timer_read32(void)
|
||||
{
|
||||
return tc_get_cycles32(&clksrc);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_GENERIC_CLOCKEVENTS
|
||||
|
||||
struct tc_clkevt_device {
|
||||
@@ -432,6 +445,7 @@ static int __init tcb_clksrc_init(struct device_node *node)
|
||||
/* setup ony channel 0 */
|
||||
tcb_setup_single_chan(&tc, best_divisor_idx);
|
||||
tc_sched_clock = tc_sched_clock_read32;
|
||||
tc_delay_timer.read_current_timer = tc_delay_timer_read32;
|
||||
} else {
|
||||
/* we have three clocks no matter what the
|
||||
* underlying platform supports.
|
||||
@@ -444,6 +458,7 @@ static int __init tcb_clksrc_init(struct device_node *node)
|
||||
/* setup both channel 0 & 1 */
|
||||
tcb_setup_dual_chan(&tc, best_divisor_idx);
|
||||
tc_sched_clock = tc_sched_clock_read;
|
||||
tc_delay_timer.read_current_timer = tc_delay_timer_read;
|
||||
}
|
||||
|
||||
/* and away we go! */
|
||||
@@ -458,6 +473,9 @@ static int __init tcb_clksrc_init(struct device_node *node)
|
||||
|
||||
sched_clock_register(tc_sched_clock, 32, divided_rate);
|
||||
|
||||
tc_delay_timer.freq = divided_rate;
|
||||
register_current_timer_delay(&tc_delay_timer);
|
||||
|
||||
return 0;
|
||||
|
||||
err_unregister_clksrc:
|
||||
|
@@ -20,6 +20,8 @@
|
||||
#define SYS_CTR_EN 0x1
|
||||
#define SYS_CTR_IRQ_MASK 0x2
|
||||
|
||||
#define SYS_CTR_CLK_DIV 0x3
|
||||
|
||||
static void __iomem *sys_ctr_base;
|
||||
static u32 cmpcr;
|
||||
|
||||
@@ -134,6 +136,9 @@ static int __init sysctr_timer_init(struct device_node *np)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* system counter clock is divided by 3 internally */
|
||||
to_sysctr.of_clk.rate /= SYS_CTR_CLK_DIV;
|
||||
|
||||
sys_ctr_base = timer_of_base(&to_sysctr);
|
||||
cmpcr = readl(sys_ctr_base + CMPCR);
|
||||
cmpcr &= ~SYS_CTR_EN;
|
||||
|
@@ -32,7 +32,7 @@
|
||||
#define NPCM7XX_Tx_INTEN BIT(29)
|
||||
#define NPCM7XX_Tx_COUNTEN BIT(30)
|
||||
#define NPCM7XX_Tx_ONESHOT 0x0
|
||||
#define NPCM7XX_Tx_OPER GENMASK(27, 3)
|
||||
#define NPCM7XX_Tx_OPER GENMASK(28, 27)
|
||||
#define NPCM7XX_Tx_MIN_PRESCALE 0x1
|
||||
#define NPCM7XX_Tx_TDR_MASK_BITS 24
|
||||
#define NPCM7XX_Tx_MAX_CNT 0xFFFFFF
|
||||
@@ -84,8 +84,6 @@ static int npcm7xx_timer_oneshot(struct clock_event_device *evt)
|
||||
|
||||
val = readl(timer_of_base(to) + NPCM7XX_REG_TCSR0);
|
||||
val &= ~NPCM7XX_Tx_OPER;
|
||||
|
||||
val = readl(timer_of_base(to) + NPCM7XX_REG_TCSR0);
|
||||
val |= NPCM7XX_START_ONESHOT_Tx;
|
||||
writel(val, timer_of_base(to) + NPCM7XX_REG_TCSR0);
|
||||
|
||||
@@ -97,12 +95,11 @@ static int npcm7xx_timer_periodic(struct clock_event_device *evt)
|
||||
struct timer_of *to = to_timer_of(evt);
|
||||
u32 val;
|
||||
|
||||
writel(timer_of_period(to), timer_of_base(to) + NPCM7XX_REG_TICR0);
|
||||
|
||||
val = readl(timer_of_base(to) + NPCM7XX_REG_TCSR0);
|
||||
val &= ~NPCM7XX_Tx_OPER;
|
||||
|
||||
writel(timer_of_period(to), timer_of_base(to) + NPCM7XX_REG_TICR0);
|
||||
val |= NPCM7XX_START_PERIODIC_Tx;
|
||||
|
||||
writel(val, timer_of_base(to) + NPCM7XX_REG_TCSR0);
|
||||
|
||||
return 0;
|
||||
|
@@ -113,8 +113,10 @@ static __init int timer_of_clk_init(struct device_node *np,
|
||||
of_clk->clk = of_clk->name ? of_clk_get_by_name(np, of_clk->name) :
|
||||
of_clk_get(np, of_clk->index);
|
||||
if (IS_ERR(of_clk->clk)) {
|
||||
pr_err("Failed to get clock for %pOF\n", np);
|
||||
return PTR_ERR(of_clk->clk);
|
||||
ret = PTR_ERR(of_clk->clk);
|
||||
if (ret != -EPROBE_DEFER)
|
||||
pr_err("Failed to get clock for %pOF\n", np);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(of_clk->clk);
|
||||
|
@@ -29,7 +29,9 @@ void __init timer_probe(void)
|
||||
|
||||
ret = init_func_ret(np);
|
||||
if (ret) {
|
||||
pr_err("Failed to initialize '%pOF': %d\n", np, ret);
|
||||
if (ret != -EPROBE_DEFER)
|
||||
pr_err("Failed to initialize '%pOF': %d\n", np,
|
||||
ret);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@@ -219,5 +219,9 @@ static int __init sun4i_timer_init(struct device_node *node)
|
||||
}
|
||||
TIMER_OF_DECLARE(sun4i, "allwinner,sun4i-a10-timer",
|
||||
sun4i_timer_init);
|
||||
TIMER_OF_DECLARE(sun8i_a23, "allwinner,sun8i-a23-timer",
|
||||
sun4i_timer_init);
|
||||
TIMER_OF_DECLARE(sun8i_v3s, "allwinner,sun8i-v3s-timer",
|
||||
sun4i_timer_init);
|
||||
TIMER_OF_DECLARE(suniv, "allwinner,suniv-f1c100s-timer",
|
||||
sun4i_timer_init);
|
||||
|
Reference in New Issue
Block a user