diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-09-17 12:35:15 -0700 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-09-17 12:35:15 -0700 | 
| commit | 7f2444d38f6bbfa12bc15e2533d8f9daa85ca02b (patch) | |
| tree | 6506ec79036890edfd9797b001391a350b5ac10f /drivers/clocksource | |
| parent | c5f12fdb8bd873aa3ffdb79512e6bdac92b257b0 (diff) | |
| parent | 77b4b5420422fc037d00b8f3f0e89b2262e4ae29 (diff) | |
| download | blackbird-op-linux-7f2444d38f6bbfa12bc15e2533d8f9daa85ca02b.tar.gz blackbird-op-linux-7f2444d38f6bbfa12bc15e2533d8f9daa85ca02b.zip  | |
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
  ...
Diffstat (limited to 'drivers/clocksource')
| -rw-r--r-- | drivers/clocksource/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/clocksource/em_sti.c | 4 | ||||
| -rw-r--r-- | drivers/clocksource/hyperv_timer.c | 45 | ||||
| -rw-r--r-- | drivers/clocksource/renesas-ostm.c | 2 | ||||
| -rw-r--r-- | drivers/clocksource/sh_cmt.c | 19 | ||||
| -rw-r--r-- | drivers/clocksource/sh_tmu.c | 5 | ||||
| -rw-r--r-- | drivers/clocksource/timer-atmel-tcb.c | 18 | ||||
| -rw-r--r-- | drivers/clocksource/timer-imx-sysctr.c | 5 | ||||
| -rw-r--r-- | drivers/clocksource/timer-npcm7xx.c | 9 | ||||
| -rw-r--r-- | drivers/clocksource/timer-of.c | 6 | ||||
| -rw-r--r-- | drivers/clocksource/timer-probe.c | 4 | ||||
| -rw-r--r-- | drivers/clocksource/timer-sun4i.c | 4 | 
12 files changed, 71 insertions, 52 deletions
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 5e9317dc3d39..a642c23b2fba 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -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. diff --git a/drivers/clocksource/em_sti.c b/drivers/clocksource/em_sti.c index 8e12b11e81b0..9039df4f90e2 100644 --- a/drivers/clocksource/em_sti.c +++ b/drivers/clocksource/em_sti.c @@ -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); diff --git a/drivers/clocksource/hyperv_timer.c b/drivers/clocksource/hyperv_timer.c index ba2c79e6a0ee..2317d4e3daaf 100644 --- a/drivers/clocksource/hyperv_timer.c +++ b/drivers/clocksource/hyperv_timer.c @@ -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); diff --git a/drivers/clocksource/renesas-ostm.c b/drivers/clocksource/renesas-ostm.c index 61d5f3b539ce..37c39b901bb1 100644 --- a/drivers/clocksource/renesas-ostm.c +++ b/drivers/clocksource/renesas-ostm.c @@ -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 diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index 55d3e03f2cd4..ef773db080e9 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c @@ -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,13 +918,25 @@ 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]  	}, diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c index 49f1c805fc95..8c4f3753b36e 100644 --- a/drivers/clocksource/sh_tmu.c +++ b/drivers/clocksource/sh_tmu.c @@ -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; diff --git a/drivers/clocksource/timer-atmel-tcb.c b/drivers/clocksource/timer-atmel-tcb.c index 6ed31f9def7e..7427b07495a8 100644 --- a/drivers/clocksource/timer-atmel-tcb.c +++ b/drivers/clocksource/timer-atmel-tcb.c @@ -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: diff --git a/drivers/clocksource/timer-imx-sysctr.c b/drivers/clocksource/timer-imx-sysctr.c index fd7d68066efb..b7c80a368a1b 100644 --- a/drivers/clocksource/timer-imx-sysctr.c +++ b/drivers/clocksource/timer-imx-sysctr.c @@ -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; diff --git a/drivers/clocksource/timer-npcm7xx.c b/drivers/clocksource/timer-npcm7xx.c index 8a30da7f083b..9780ffd8010e 100644 --- a/drivers/clocksource/timer-npcm7xx.c +++ b/drivers/clocksource/timer-npcm7xx.c @@ -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; diff --git a/drivers/clocksource/timer-of.c b/drivers/clocksource/timer-of.c index 80542289fae7..d8c2bd4391d0 100644 --- a/drivers/clocksource/timer-of.c +++ b/drivers/clocksource/timer-of.c @@ -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); diff --git a/drivers/clocksource/timer-probe.c b/drivers/clocksource/timer-probe.c index dda1946e84dd..ee9574da53c0 100644 --- a/drivers/clocksource/timer-probe.c +++ b/drivers/clocksource/timer-probe.c @@ -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;  		} diff --git a/drivers/clocksource/timer-sun4i.c b/drivers/clocksource/timer-sun4i.c index 65f38f6ca714..0ba8155b8287 100644 --- a/drivers/clocksource/timer-sun4i.c +++ b/drivers/clocksource/timer-sun4i.c @@ -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);  | 

