diff options
175 files changed, 2498 insertions, 3166 deletions
| diff --git a/Documentation/devicetree/bindings/timer/faraday,fttmr010.txt b/Documentation/devicetree/bindings/timer/faraday,fttmr010.txt index b73ca6cd07f8..195792270414 100644 --- a/Documentation/devicetree/bindings/timer/faraday,fttmr010.txt +++ b/Documentation/devicetree/bindings/timer/faraday,fttmr010.txt @@ -7,7 +7,11 @@ Required properties:  - compatible : Must be one of    "faraday,fttmr010" -  "cortina,gemini-timer" +  "cortina,gemini-timer", "faraday,fttmr010" +  "moxa,moxart-timer", "faraday,fttmr010" +  "aspeed,ast2400-timer" +  "aspeed,ast2500-timer" +  - reg : Should contain registers location and length  - interrupts : Should contain the three timer interrupts usually with    flags for falling edge diff --git a/Documentation/devicetree/bindings/timer/moxa,moxart-timer.txt b/Documentation/devicetree/bindings/timer/moxa,moxart-timer.txt deleted file mode 100644 index e207c11630af..000000000000 --- a/Documentation/devicetree/bindings/timer/moxa,moxart-timer.txt +++ /dev/null @@ -1,19 +0,0 @@ -MOXA ART timer - -Required properties: - -- compatible : Must be one of: - 	- "moxa,moxart-timer" - 	- "aspeed,ast2400-timer" -- reg : Should contain registers location and length -- interrupts : Should contain the timer interrupt number -- clocks : Should contain phandle for the clock that drives the counter - -Example: - -	timer: timer@98400000 { -		compatible = "moxa,moxart-timer"; -		reg = <0x98400000 0x42>; -		interrupts = <19 1>; -		clocks = <&coreclk>; -	}; diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild index 7bee4e4799fd..3e74ca5e6402 100644 --- a/arch/arc/include/asm/Kbuild +++ b/arch/arc/include/asm/Kbuild @@ -36,7 +36,6 @@ generic-y += preempt.h  generic-y += resource.h  generic-y += sembuf.h  generic-y += shmbuf.h -generic-y += siginfo.h  generic-y += socket.h  generic-y += sockios.h  generic-y += stat.h diff --git a/arch/arc/include/uapi/asm/Kbuild b/arch/arc/include/uapi/asm/Kbuild index b15bf6bc0e94..b55fc2ae1e8c 100644 --- a/arch/arc/include/uapi/asm/Kbuild +++ b/arch/arc/include/uapi/asm/Kbuild @@ -1,2 +1,4 @@  # UAPI Header export list  include include/uapi/asm-generic/Kbuild.asm + +generic-y += siginfo.h diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c index fc8211f338ad..666613fde91d 100644 --- a/arch/arc/kernel/setup.c +++ b/arch/arc/kernel/setup.c @@ -470,7 +470,7 @@ void __init setup_arch(char **cmdline_p)  void __init time_init(void)  {  	of_clk_init(NULL); -	clocksource_probe(); +	timer_probe();  }  static int __init customize_machine(void) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 6491be556ddc..6281c3e5a673 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -337,7 +337,7 @@ config ARCH_MULTIPLATFORM  	select ARM_HAS_SG_CHAIN  	select ARM_PATCH_PHYS_VIRT  	select AUTO_ZRELADDR -	select CLKSRC_OF +	select TIMER_OF  	select COMMON_CLK  	select GENERIC_CLOCKEVENTS  	select MIGHT_HAVE_PCI @@ -351,7 +351,7 @@ config ARM_SINGLE_ARMV7M  	depends on !MMU  	select ARM_NVIC  	select AUTO_ZRELADDR -	select CLKSRC_OF +	select TIMER_OF  	select COMMON_CLK  	select CPU_V7M  	select GENERIC_CLOCKEVENTS @@ -532,7 +532,7 @@ config ARCH_PXA  	select CLKDEV_LOOKUP  	select CLKSRC_PXA  	select CLKSRC_MMIO -	select CLKSRC_OF +	select TIMER_OF  	select CPU_XSCALE if !CPU_XSC3  	select GENERIC_CLOCKEVENTS  	select GPIO_PXA @@ -571,7 +571,7 @@ config ARCH_SA1100  	select CLKDEV_LOOKUP  	select CLKSRC_MMIO  	select CLKSRC_PXA -	select CLKSRC_OF if OF +	select TIMER_OF if OF  	select CPU_FREQ  	select CPU_SA1100  	select GENERIC_CLOCKEVENTS @@ -1357,7 +1357,7 @@ config HAVE_ARM_ARCH_TIMER  config HAVE_ARM_TWD  	bool -	select CLKSRC_OF if OF +	select TIMER_OF if OF  	help  	  This options enables support for the ARM timer and watchdog unit diff --git a/arch/arm/boot/dts/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed-g4.dtsi index 8c6bc29eb7f6..3e74929d3289 100644 --- a/arch/arm/boot/dts/aspeed-g4.dtsi +++ b/arch/arm/boot/dts/aspeed-g4.dtsi @@ -893,6 +893,7 @@  				//interrupts = <16 17 18 35 36 37 38 39>;  				interrupts = <16>;  				clocks = <&clk_apb>; +				clock-names = "PCLK";  			};  			wdt1: wdt@1e785000 { diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi index a0bea4a6ec77..1e6c701da853 100644 --- a/arch/arm/boot/dts/aspeed-g5.dtsi +++ b/arch/arm/boot/dts/aspeed-g5.dtsi @@ -1000,6 +1000,7 @@  				//interrupts = <16 17 18 35 36 37 38 39>;  				interrupts = <16>;  				clocks = <&clk_apb>; +				clock-names = "PCLK";  			}; diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild index 3a36d99ff836..d8360501c082 100644 --- a/arch/arm/include/asm/Kbuild +++ b/arch/arm/include/asm/Kbuild @@ -28,7 +28,6 @@ generic-y += segment.h  generic-y += sembuf.h  generic-y += serial.h  generic-y += shmbuf.h -generic-y += siginfo.h  generic-y += simd.h  generic-y += sizes.h  generic-y += socket.h diff --git a/arch/arm/include/uapi/asm/Kbuild b/arch/arm/include/uapi/asm/Kbuild index 607f702c2d62..e9b098d6b766 100644 --- a/arch/arm/include/uapi/asm/Kbuild +++ b/arch/arm/include/uapi/asm/Kbuild @@ -4,3 +4,5 @@ include include/uapi/asm-generic/Kbuild.asm  genhdr-y += unistd-common.h  genhdr-y += unistd-oabi.h  genhdr-y += unistd-eabi.h + +generic-y += siginfo.h diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c index 895ae5197159..b30eafeef096 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c @@ -403,7 +403,7 @@ out:  	WARN(err, "twd_local_timer_of_register failed (%d)\n", err);  	return err;  } -CLOCKSOURCE_OF_DECLARE(arm_twd_a9, "arm,cortex-a9-twd-timer", twd_local_timer_of_register); -CLOCKSOURCE_OF_DECLARE(arm_twd_a5, "arm,cortex-a5-twd-timer", twd_local_timer_of_register); -CLOCKSOURCE_OF_DECLARE(arm_twd_11mp, "arm,arm11mp-twd-timer", twd_local_timer_of_register); +TIMER_OF_DECLARE(arm_twd_a9, "arm,cortex-a9-twd-timer", twd_local_timer_of_register); +TIMER_OF_DECLARE(arm_twd_a5, "arm,cortex-a5-twd-timer", twd_local_timer_of_register); +TIMER_OF_DECLARE(arm_twd_11mp, "arm,arm11mp-twd-timer", twd_local_timer_of_register);  #endif diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c index 97b22fa7cb3a..629f8e9981f1 100644 --- a/arch/arm/kernel/time.c +++ b/arch/arm/kernel/time.c @@ -120,6 +120,6 @@ void __init time_init(void)  #ifdef CONFIG_COMMON_CLK  		of_clk_init(NULL);  #endif -		clocksource_probe(); +		timer_probe();  	}  } diff --git a/arch/arm/mach-aspeed/Kconfig b/arch/arm/mach-aspeed/Kconfig index f3f8c5c658db..2d5570e6e186 100644 --- a/arch/arm/mach-aspeed/Kconfig +++ b/arch/arm/mach-aspeed/Kconfig @@ -4,7 +4,7 @@ menuconfig ARCH_ASPEED  	select SRAM  	select WATCHDOG  	select ASPEED_WATCHDOG -	select MOXART_TIMER +	select FTTMR010_TIMER  	select MFD_SYSCON  	select PINCTRL  	help diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig index f9389c5910e7..f23a23934162 100644 --- a/arch/arm/mach-bcm/Kconfig +++ b/arch/arm/mach-bcm/Kconfig @@ -150,7 +150,7 @@ config ARCH_BCM2835  	select ARM_ERRATA_411920 if ARCH_MULTI_V6  	select ARM_TIMER_SP804  	select HAVE_ARM_ARCH_TIMER if ARCH_MULTI_V7 -	select CLKSRC_OF +	select TIMER_OF  	select BCM2835_TIMER  	select PINCTRL  	select PINCTRL_BCM2835 diff --git a/arch/arm/mach-clps711x/Kconfig b/arch/arm/mach-clps711x/Kconfig index 61284b9389cf..f385b1fcafef 100644 --- a/arch/arm/mach-clps711x/Kconfig +++ b/arch/arm/mach-clps711x/Kconfig @@ -2,7 +2,7 @@ menuconfig ARCH_CLPS711X  	bool "Cirrus Logic EP721x/EP731x-based"  	depends on ARCH_MULTI_V4T  	select AUTO_ZRELADDR -	select CLKSRC_OF +	select TIMER_OF  	select CLPS711X_TIMER  	select COMMON_CLK  	select CPU_ARM720T diff --git a/arch/arm/mach-mediatek/mediatek.c b/arch/arm/mach-mediatek/mediatek.c index a6e3c98b95ed..c3cf215773b2 100644 --- a/arch/arm/mach-mediatek/mediatek.c +++ b/arch/arm/mach-mediatek/mediatek.c @@ -41,7 +41,7 @@ static void __init mediatek_timer_init(void)  	}  	of_clk_init(NULL); -	clocksource_probe(); +	timer_probe();  };  static const char * const mediatek_board_dt_compat[] = { diff --git a/arch/arm/mach-moxart/Kconfig b/arch/arm/mach-moxart/Kconfig index 70db2abf6163..a4a91f9a3301 100644 --- a/arch/arm/mach-moxart/Kconfig +++ b/arch/arm/mach-moxart/Kconfig @@ -4,7 +4,7 @@ menuconfig ARCH_MOXART  	select CPU_FA526  	select ARM_DMA_MEM_BUFFERABLE  	select FARADAY_FTINTC010 -	select MOXART_TIMER +	select FTTMR010_TIMER  	select GPIOLIB  	select PHYLIB if NETDEVICES  	help diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index 07dd692c4737..ae4bb9fdc483 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c @@ -497,7 +497,7 @@ void __init omap_init_time(void)  	__omap_sync32k_timer_init(1, "timer_32k_ck", "ti,timer-alwon",  			2, "timer_sys_ck", NULL, false); -	clocksource_probe(); +	timer_probe();  }  #if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_SOC_AM43XX) @@ -506,7 +506,7 @@ void __init omap3_secure_sync32k_timer_init(void)  	__omap_sync32k_timer_init(12, "secure_32k_fck", "ti,timer-secure",  			2, "timer_sys_ck", NULL, false); -	clocksource_probe(); +	timer_probe();  }  #endif /* CONFIG_ARCH_OMAP3 */ @@ -517,7 +517,7 @@ void __init omap3_gptimer_timer_init(void)  	__omap_sync32k_timer_init(2, "timer_sys_ck", NULL,  			1, "timer_sys_ck", "ti,timer-alwon", true);  	if (of_have_populated_dt()) -		clocksource_probe(); +		timer_probe();  }  #endif @@ -532,7 +532,7 @@ static void __init omap4_sync32k_timer_init(void)  void __init omap4_local_timer_init(void)  {  	omap4_sync32k_timer_init(); -	clocksource_probe(); +	timer_probe();  }  #endif @@ -656,7 +656,7 @@ void __init omap5_realtime_timer_init(void)  	omap4_sync32k_timer_init();  	realtime_counter_init(); -	clocksource_probe(); +	timer_probe();  }  #endif /* CONFIG_SOC_OMAP5 || CONFIG_SOC_DRA7XX */ diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c index ef0500a4c8ad..5ab834ebcb49 100644 --- a/arch/arm/mach-rockchip/rockchip.c +++ b/arch/arm/mach-rockchip/rockchip.c @@ -55,7 +55,7 @@ static void __init rockchip_timer_init(void)  	}  	of_clk_init(NULL); -	clocksource_probe(); +	timer_probe();  }  static void __init rockchip_dt_init(void) diff --git a/arch/arm/mach-s3c24xx/Kconfig b/arch/arm/mach-s3c24xx/Kconfig index 4b1690acb6a5..f07da82ebfea 100644 --- a/arch/arm/mach-s3c24xx/Kconfig +++ b/arch/arm/mach-s3c24xx/Kconfig @@ -394,7 +394,7 @@ config MACH_SMDK2416  config MACH_S3C2416_DT  	bool "Samsung S3C2416 machine using devicetree" -	select CLKSRC_OF +	select TIMER_OF  	select USE_OF  	select PINCTRL  	select PINCTRL_S3C24XX diff --git a/arch/arm/mach-s3c64xx/Kconfig b/arch/arm/mach-s3c64xx/Kconfig index 459214fa20b4..71a49343d711 100644 --- a/arch/arm/mach-s3c64xx/Kconfig +++ b/arch/arm/mach-s3c64xx/Kconfig @@ -336,7 +336,7 @@ config MACH_WLF_CRAGG_6410  config MACH_S3C64XX_DT  	bool "Samsung S3C6400/S3C6410 machine using Device Tree" -	select CLKSRC_OF +	select TIMER_OF  	select CPU_S3C6400  	select CPU_S3C6410  	select PINCTRL diff --git a/arch/arm/mach-shmobile/setup-rcar-gen2.c b/arch/arm/mach-shmobile/setup-rcar-gen2.c index 52d466b75973..a6e74f481dea 100644 --- a/arch/arm/mach-shmobile/setup-rcar-gen2.c +++ b/arch/arm/mach-shmobile/setup-rcar-gen2.c @@ -113,7 +113,7 @@ void __init rcar_gen2_timer_init(void)  #endif /* CONFIG_ARM_ARCH_TIMER */  	of_clk_init(NULL); -	clocksource_probe(); +	timer_probe();  }  struct memory_reserve_config { diff --git a/arch/arm/mach-spear/spear13xx.c b/arch/arm/mach-spear/spear13xx.c index ca2f6a82a414..31c43cabf362 100644 --- a/arch/arm/mach-spear/spear13xx.c +++ b/arch/arm/mach-spear/spear13xx.c @@ -124,5 +124,5 @@ void __init spear13xx_timer_init(void)  	clk_put(pclk);  	spear_setup_of_timer(); -	clocksource_probe(); +	timer_probe();  } diff --git a/arch/arm/mach-sunxi/sunxi.c b/arch/arm/mach-sunxi/sunxi.c index f44e3acb5c90..7ab353fb25f2 100644 --- a/arch/arm/mach-sunxi/sunxi.c +++ b/arch/arm/mach-sunxi/sunxi.c @@ -42,7 +42,7 @@ static void __init sun6i_timer_init(void)  	of_clk_init(NULL);  	if (IS_ENABLED(CONFIG_RESET_CONTROLLER))  		sun6i_reset_init(); -	clocksource_probe(); +	timer_probe();  }  DT_MACHINE_START(SUN6I_DT, "Allwinner sun6i (A31) Family") diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c index a4910ea6811a..048f15e8c669 100644 --- a/arch/arm/mach-u300/core.c +++ b/arch/arm/mach-u300/core.c @@ -407,7 +407,7 @@ static const char * u300_board_compat[] = {  DT_MACHINE_START(U300_DT, "U300 S335/B335 (Device Tree)")  	.map_io		= u300_map_io,  	.init_irq	= u300_init_irq_dt, -	.init_time	= clocksource_probe, +	.init_time	= timer_probe,  	.init_machine	= u300_init_machine_dt,  	.restart	= u300_restart,  	.dt_compat      = u300_board_compat, diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c index ed118648313f..6aba9ebf8041 100644 --- a/arch/arm/mach-zynq/common.c +++ b/arch/arm/mach-zynq/common.c @@ -150,7 +150,7 @@ static void __init zynq_timer_init(void)  {  	zynq_clock_init();  	of_clk_init(NULL); -	clocksource_probe(); +	timer_probe();  }  static struct map_desc zynq_cortex_a9_scu_map __initdata = { diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms index 73272f43ca01..9ed0a659046b 100644 --- a/arch/arm64/Kconfig.platforms +++ b/arch/arm64/Kconfig.platforms @@ -18,7 +18,7 @@ config ARCH_ALPINE  config ARCH_BCM2835  	bool "Broadcom BCM2835 family" -	select CLKSRC_OF +	select TIMER_OF  	select GPIOLIB  	select PINCTRL  	select PINCTRL_BCM2835 @@ -178,7 +178,7 @@ config ARCH_TEGRA  	select ARCH_HAS_RESET_CONTROLLER  	select CLKDEV_LOOKUP  	select CLKSRC_MMIO -	select CLKSRC_OF +	select TIMER_OF  	select GENERIC_CLOCKEVENTS  	select GPIOLIB  	select PINCTRL diff --git a/arch/arm64/kernel/time.c b/arch/arm64/kernel/time.c index 59779699a1a4..da33c90248e9 100644 --- a/arch/arm64/kernel/time.c +++ b/arch/arm64/kernel/time.c @@ -70,7 +70,7 @@ void __init time_init(void)  	u32 arch_timer_rate;  	of_clk_init(NULL); -	clocksource_probe(); +	timer_probe();  	tick_setup_hrtimer_broadcast(); diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c index d0cb007fa482..7492d9009610 100644 --- a/arch/arm64/kernel/vdso.c +++ b/arch/arm64/kernel/vdso.c @@ -220,10 +220,8 @@ void update_vsyscall(struct timekeeper *tk)  	if (!use_syscall) {  		/* tkr_mono.cycle_last == tkr_raw.cycle_last */  		vdso_data->cs_cycle_last	= tk->tkr_mono.cycle_last; -		vdso_data->raw_time_sec		= tk->raw_time.tv_sec; -		vdso_data->raw_time_nsec	= (tk->raw_time.tv_nsec << -						   tk->tkr_raw.shift) + -						  tk->tkr_raw.xtime_nsec; +		vdso_data->raw_time_sec         = tk->raw_sec; +		vdso_data->raw_time_nsec        = tk->tkr_raw.xtime_nsec;  		vdso_data->xtime_clock_sec	= tk->xtime_sec;  		vdso_data->xtime_clock_nsec	= tk->tkr_mono.xtime_nsec;  		vdso_data->cs_mono_mult		= tk->tkr_mono.mult; diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild index f0eaf0475e7e..a3c8d05c4cc7 100644 --- a/arch/c6x/include/asm/Kbuild +++ b/arch/c6x/include/asm/Kbuild @@ -45,7 +45,6 @@ generic-y += sembuf.h  generic-y += serial.h  generic-y += shmbuf.h  generic-y += shmparam.h -generic-y += siginfo.h  generic-y += signal.h  generic-y += socket.h  generic-y += sockios.h diff --git a/arch/c6x/include/uapi/asm/Kbuild b/arch/c6x/include/uapi/asm/Kbuild index 13a97aa2285f..1c44d3b3eba0 100644 --- a/arch/c6x/include/uapi/asm/Kbuild +++ b/arch/c6x/include/uapi/asm/Kbuild @@ -2,3 +2,4 @@  include include/uapi/asm-generic/Kbuild.asm  generic-y += kvm_para.h +generic-y += siginfo.h diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild index 2890099992a9..acc5781100c2 100644 --- a/arch/cris/include/asm/Kbuild +++ b/arch/cris/include/asm/Kbuild @@ -36,7 +36,6 @@ generic-y += resource.h  generic-y += sections.h  generic-y += sembuf.h  generic-y += shmbuf.h -generic-y += siginfo.h  generic-y += socket.h  generic-y += sockios.h  generic-y += statfs.h diff --git a/arch/cris/include/uapi/asm/Kbuild b/arch/cris/include/uapi/asm/Kbuild index b15bf6bc0e94..b55fc2ae1e8c 100644 --- a/arch/cris/include/uapi/asm/Kbuild +++ b/arch/cris/include/uapi/asm/Kbuild @@ -1,2 +1,4 @@  # UAPI Header export list  include include/uapi/asm-generic/Kbuild.asm + +generic-y += siginfo.h diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig index 3ae852507e57..6e3d36f37a02 100644 --- a/arch/h8300/Kconfig +++ b/arch/h8300/Kconfig @@ -15,7 +15,7 @@ config H8300  	select OF_IRQ  	select OF_EARLY_FLATTREE  	select HAVE_MEMBLOCK -	select CLKSRC_OF +	select TIMER_OF  	select H8300_TMR8  	select HAVE_KERNEL_GZIP  	select HAVE_KERNEL_LZO diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild index 757cdeb24e6e..99c824608a31 100644 --- a/arch/h8300/include/asm/Kbuild +++ b/arch/h8300/include/asm/Kbuild @@ -54,7 +54,6 @@ generic-y += serial.h  generic-y += setup.h  generic-y += shmbuf.h  generic-y += shmparam.h -generic-y += siginfo.h  generic-y += sizes.h  generic-y += socket.h  generic-y += sockios.h diff --git a/arch/h8300/include/uapi/asm/Kbuild b/arch/h8300/include/uapi/asm/Kbuild index b15bf6bc0e94..b55fc2ae1e8c 100644 --- a/arch/h8300/include/uapi/asm/Kbuild +++ b/arch/h8300/include/uapi/asm/Kbuild @@ -1,2 +1,4 @@  # UAPI Header export list  include include/uapi/asm-generic/Kbuild.asm + +generic-y += siginfo.h diff --git a/arch/h8300/kernel/setup.c b/arch/h8300/kernel/setup.c index c8c25a4e9e48..6be15d634650 100644 --- a/arch/h8300/kernel/setup.c +++ b/arch/h8300/kernel/setup.c @@ -246,5 +246,5 @@ void __init calibrate_delay(void)  void __init time_init(void)  {  	of_clk_init(NULL); -	clocksource_probe(); +	timer_probe();  } diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild index 6b45ef79eb8f..0fc9cb04e6ad 100644 --- a/arch/hexagon/include/asm/Kbuild +++ b/arch/hexagon/include/asm/Kbuild @@ -41,7 +41,6 @@ generic-y += sembuf.h  generic-y += serial.h  generic-y += shmbuf.h  generic-y += shmparam.h -generic-y += siginfo.h  generic-y += sizes.h  generic-y += socket.h  generic-y += sockios.h diff --git a/arch/hexagon/include/uapi/asm/Kbuild b/arch/hexagon/include/uapi/asm/Kbuild index b15bf6bc0e94..b55fc2ae1e8c 100644 --- a/arch/hexagon/include/uapi/asm/Kbuild +++ b/arch/hexagon/include/uapi/asm/Kbuild @@ -1,2 +1,4 @@  # UAPI Header export list  include include/uapi/asm-generic/Kbuild.asm + +generic-y += siginfo.h diff --git a/arch/ia64/include/asm/siginfo.h b/arch/ia64/include/asm/siginfo.h deleted file mode 100644 index 6f2e2dd0f28f..000000000000 --- a/arch/ia64/include/asm/siginfo.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Based on <asm-i386/siginfo.h>. - * - * Modified 1998-2002 - *	David Mosberger-Tang <[email protected]>, Hewlett-Packard Co - */ -#ifndef _ASM_IA64_SIGINFO_H -#define _ASM_IA64_SIGINFO_H - -#include <linux/string.h> -#include <uapi/asm/siginfo.h> - -static inline void -copy_siginfo (siginfo_t *to, siginfo_t *from) -{ -	if (from->si_code < 0) -		memcpy(to, from, sizeof(siginfo_t)); -	else -		/* _sigchld is currently the largest know union member */ -		memcpy(to, from, 4*sizeof(int) + sizeof(from->_sifields._sigchld)); -} - -#endif /* _ASM_IA64_SIGINFO_H */ diff --git a/arch/ia64/include/uapi/asm/siginfo.h b/arch/ia64/include/uapi/asm/siginfo.h index f72bf0172bb2..4694c64252d6 100644 --- a/arch/ia64/include/uapi/asm/siginfo.h +++ b/arch/ia64/include/uapi/asm/siginfo.h @@ -11,7 +11,6 @@  #define __ARCH_SI_PREAMBLE_SIZE	(4 * sizeof(int))  #define HAVE_ARCH_SIGINFO_T -#define HAVE_ARCH_COPY_SIGINFO  #define HAVE_ARCH_COPY_SIGINFO_TO_USER  #include <asm-generic/siginfo.h> diff --git a/arch/m32r/include/uapi/asm/Kbuild b/arch/m32r/include/uapi/asm/Kbuild index b15bf6bc0e94..c94ee54210bc 100644 --- a/arch/m32r/include/uapi/asm/Kbuild +++ b/arch/m32r/include/uapi/asm/Kbuild @@ -1,2 +1,4 @@  # UAPI Header export list  include include/uapi/asm-generic/Kbuild.asm + +generic-y	+= siginfo.h diff --git a/arch/m32r/include/uapi/asm/siginfo.h b/arch/m32r/include/uapi/asm/siginfo.h deleted file mode 100644 index 7d9cd9ebfd0e..000000000000 --- a/arch/m32r/include/uapi/asm/siginfo.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _M32R_SIGINFO_H -#define _M32R_SIGINFO_H - -#include <asm-generic/siginfo.h> - -#endif /* _M32R_SIGINFO_H */ diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild index 82005d2ff717..5ecf4e47b2e2 100644 --- a/arch/m68k/include/asm/Kbuild +++ b/arch/m68k/include/asm/Kbuild @@ -25,7 +25,6 @@ generic-y += preempt.h  generic-y += resource.h  generic-y += sections.h  generic-y += shmparam.h -generic-y += siginfo.h  generic-y += spinlock.h  generic-y += statfs.h  generic-y += termios.h diff --git a/arch/m68k/include/uapi/asm/Kbuild b/arch/m68k/include/uapi/asm/Kbuild index 64368077235a..68b45cc87e2c 100644 --- a/arch/m68k/include/uapi/asm/Kbuild +++ b/arch/m68k/include/uapi/asm/Kbuild @@ -5,6 +5,7 @@ generic-y += auxvec.h  generic-y += msgbuf.h  generic-y += sembuf.h  generic-y += shmbuf.h +generic-y += siginfo.h  generic-y += socket.h  generic-y += sockios.h  generic-y += termbits.h diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig index 85885a501dce..8e47121b8b8b 100644 --- a/arch/microblaze/Kconfig +++ b/arch/microblaze/Kconfig @@ -4,7 +4,7 @@ config MICROBLAZE  	select ARCH_MIGHT_HAVE_PC_PARPORT  	select ARCH_WANT_IPC_PARSE_VERSION  	select BUILDTIME_EXTABLE_SORT -	select CLKSRC_OF +	select TIMER_OF  	select CLONE_BACKWARDS3  	select COMMON_CLK  	select GENERIC_ATOMIC64 diff --git a/arch/microblaze/include/uapi/asm/Kbuild b/arch/microblaze/include/uapi/asm/Kbuild index 2178c78c7c1a..cb6784f4a427 100644 --- a/arch/microblaze/include/uapi/asm/Kbuild +++ b/arch/microblaze/include/uapi/asm/Kbuild @@ -2,3 +2,4 @@  include include/uapi/asm-generic/Kbuild.asm  generic-y += types.h +generic-y += siginfo.h diff --git a/arch/microblaze/kernel/setup.c b/arch/microblaze/kernel/setup.c index f31ebb5dc26c..be98ffe28ca8 100644 --- a/arch/microblaze/kernel/setup.c +++ b/arch/microblaze/kernel/setup.c @@ -192,7 +192,7 @@ void __init time_init(void)  {  	of_clk_init(NULL);  	setup_cpuinfo_clk(); -	clocksource_probe(); +	timer_probe();  }  #ifdef CONFIG_DEBUG_FS diff --git a/arch/microblaze/kernel/timer.c b/arch/microblaze/kernel/timer.c index 545ccd46edb3..ea2d83f1f4bb 100644 --- a/arch/microblaze/kernel/timer.c +++ b/arch/microblaze/kernel/timer.c @@ -335,5 +335,5 @@ static int __init xilinx_timer_init(struct device_node *timer)  	return 0;  } -CLOCKSOURCE_OF_DECLARE(xilinx_timer, "xlnx,xps-timer-1.00.a", +TIMER_OF_DECLARE(xilinx_timer, "xlnx,xps-timer-1.00.a",  		       xilinx_timer_init); diff --git a/arch/mips/generic/init.c b/arch/mips/generic/init.c index 4af619215410..1231b5a17b37 100644 --- a/arch/mips/generic/init.c +++ b/arch/mips/generic/init.c @@ -161,7 +161,7 @@ void __init plat_time_init(void)  		}  	} -	clocksource_probe(); +	timer_probe();  }  void __init arch_init_irq(void) diff --git a/arch/mips/mti-malta/malta-time.c b/arch/mips/mti-malta/malta-time.c index 289edcfadd7c..cea4ec909806 100644 --- a/arch/mips/mti-malta/malta-time.c +++ b/arch/mips/mti-malta/malta-time.c @@ -265,7 +265,7 @@ void __init plat_time_init(void)  		       (freq%1000000)*100/1000000);  #ifdef CONFIG_CLKSRC_MIPS_GIC  		update_gic_frequency_dt(); -		clocksource_probe(); +		timer_probe();  #endif  	}  #endif diff --git a/arch/mips/pic32/pic32mzda/time.c b/arch/mips/pic32/pic32mzda/time.c index 62a0a78b6c64..1894e50939b5 100644 --- a/arch/mips/pic32/pic32mzda/time.c +++ b/arch/mips/pic32/pic32mzda/time.c @@ -64,5 +64,5 @@ void __init plat_time_init(void)  	pr_info("CPU Clock: %ldMHz\n", rate / 1000000);  	mips_hpt_frequency = rate / 2; -	clocksource_probe(); +	timer_probe();  } diff --git a/arch/mips/pistachio/time.c b/arch/mips/pistachio/time.c index 1022201b2beb..17a0f1dec05b 100644 --- a/arch/mips/pistachio/time.c +++ b/arch/mips/pistachio/time.c @@ -39,7 +39,7 @@ void __init plat_time_init(void)  	struct clk *clk;  	of_clk_init(NULL); -	clocksource_probe(); +	timer_probe();  	np = of_get_cpu_node(0, NULL);  	if (!np) { diff --git a/arch/mips/ralink/Kconfig b/arch/mips/ralink/Kconfig index 9825dee10bc1..710b04cf4851 100644 --- a/arch/mips/ralink/Kconfig +++ b/arch/mips/ralink/Kconfig @@ -4,7 +4,7 @@ config CLKEVT_RT3352  	bool  	depends on SOC_RT305X || SOC_MT7620  	default y -	select CLKSRC_OF +	select TIMER_OF  	select CLKSRC_MMIO  config RALINK_ILL_ACC diff --git a/arch/mips/ralink/cevt-rt3352.c b/arch/mips/ralink/cevt-rt3352.c index b8a1376165b0..92f284d2b802 100644 --- a/arch/mips/ralink/cevt-rt3352.c +++ b/arch/mips/ralink/cevt-rt3352.c @@ -152,4 +152,4 @@ static int __init ralink_systick_init(struct device_node *np)  	return 0;  } -CLOCKSOURCE_OF_DECLARE(systick, "ralink,cevt-systick", ralink_systick_init); +TIMER_OF_DECLARE(systick, "ralink,cevt-systick", ralink_systick_init); diff --git a/arch/mips/ralink/clk.c b/arch/mips/ralink/clk.c index df795885eace..eb1c61917eb7 100644 --- a/arch/mips/ralink/clk.c +++ b/arch/mips/ralink/clk.c @@ -82,5 +82,5 @@ void __init plat_time_init(void)  	pr_info("CPU Clock: %ldMHz\n", clk_get_rate(clk) / 1000000);  	mips_hpt_frequency = clk_get_rate(clk) / 2;  	clk_put(clk); -	clocksource_probe(); +	timer_probe();  } diff --git a/arch/mips/ralink/timer-gic.c b/arch/mips/ralink/timer-gic.c index 069771dbec42..b5f07d21fcf2 100644 --- a/arch/mips/ralink/timer-gic.c +++ b/arch/mips/ralink/timer-gic.c @@ -20,5 +20,5 @@ void __init plat_time_init(void)  	ralink_of_remap();  	of_clk_init(NULL); -	clocksource_probe(); +	timer_probe();  } diff --git a/arch/mips/xilfpga/time.c b/arch/mips/xilfpga/time.c index cbb3fca7b6fa..36f3f1870ee2 100644 --- a/arch/mips/xilfpga/time.c +++ b/arch/mips/xilfpga/time.c @@ -22,7 +22,7 @@ void __init plat_time_init(void)  	struct clk *clk;  	of_clk_init(NULL); -	clocksource_probe(); +	timer_probe();  	np = of_get_cpu_node(0, NULL);  	if (!np) { diff --git a/arch/mn10300/include/uapi/asm/Kbuild b/arch/mn10300/include/uapi/asm/Kbuild index b15bf6bc0e94..c94ee54210bc 100644 --- a/arch/mn10300/include/uapi/asm/Kbuild +++ b/arch/mn10300/include/uapi/asm/Kbuild @@ -1,2 +1,4 @@  # UAPI Header export list  include include/uapi/asm-generic/Kbuild.asm + +generic-y	+= siginfo.h diff --git a/arch/mn10300/include/uapi/asm/siginfo.h b/arch/mn10300/include/uapi/asm/siginfo.h deleted file mode 100644 index 0815d29d82e5..000000000000 --- a/arch/mn10300/include/uapi/asm/siginfo.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/siginfo.h> diff --git a/arch/nios2/Kconfig b/arch/nios2/Kconfig index a72d5f0de692..c587764b9c5a 100644 --- a/arch/nios2/Kconfig +++ b/arch/nios2/Kconfig @@ -1,6 +1,6 @@  config NIOS2  	def_bool y -	select CLKSRC_OF +	select TIMER_OF  	select GENERIC_ATOMIC64  	select GENERIC_CLOCKEVENTS  	select GENERIC_CPU_DEVICES diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild index 727dbb333f60..e1a843def56f 100644 --- a/arch/nios2/include/asm/Kbuild +++ b/arch/nios2/include/asm/Kbuild @@ -47,7 +47,6 @@ generic-y += segment.h  generic-y += sembuf.h  generic-y += serial.h  generic-y += shmbuf.h -generic-y += siginfo.h  generic-y += signal.h  generic-y += socket.h  generic-y += sockios.h diff --git a/arch/nios2/include/uapi/asm/Kbuild b/arch/nios2/include/uapi/asm/Kbuild index 374bd123329f..51eff5bc2eb4 100644 --- a/arch/nios2/include/uapi/asm/Kbuild +++ b/arch/nios2/include/uapi/asm/Kbuild @@ -2,4 +2,5 @@  include include/uapi/asm-generic/Kbuild.asm  generic-y += setup.h +generic-y += siginfo.h  generic-y += ucontext.h diff --git a/arch/nios2/kernel/time.c b/arch/nios2/kernel/time.c index 6e2bdc9b8530..645129aaa9a0 100644 --- a/arch/nios2/kernel/time.c +++ b/arch/nios2/kernel/time.c @@ -350,7 +350,7 @@ void __init time_init(void)  	if (count < 2)  		panic("%d timer is found, it needs 2 timers in system\n", count); -	clocksource_probe(); +	timer_probe();  } -CLOCKSOURCE_OF_DECLARE(nios2_timer, ALTR_TIMER_COMPATIBLE, nios2_time_init); +TIMER_OF_DECLARE(nios2_timer, ALTR_TIMER_COMPATIBLE, nios2_time_init); diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild index fdbcf0bf44a4..091585addb91 100644 --- a/arch/openrisc/include/asm/Kbuild +++ b/arch/openrisc/include/asm/Kbuild @@ -46,7 +46,6 @@ generic-y += sembuf.h  generic-y += setup.h  generic-y += shmbuf.h  generic-y += shmparam.h -generic-y += siginfo.h  generic-y += signal.h  generic-y += socket.h  generic-y += sockios.h diff --git a/arch/openrisc/include/uapi/asm/Kbuild b/arch/openrisc/include/uapi/asm/Kbuild index b15bf6bc0e94..b55fc2ae1e8c 100644 --- a/arch/openrisc/include/uapi/asm/Kbuild +++ b/arch/openrisc/include/uapi/asm/Kbuild @@ -1,2 +1,4 @@  # UAPI Header export list  include include/uapi/asm-generic/Kbuild.asm + +generic-y += siginfo.h diff --git a/arch/score/include/uapi/asm/Kbuild b/arch/score/include/uapi/asm/Kbuild index b15bf6bc0e94..c94ee54210bc 100644 --- a/arch/score/include/uapi/asm/Kbuild +++ b/arch/score/include/uapi/asm/Kbuild @@ -1,2 +1,4 @@  # UAPI Header export list  include include/uapi/asm-generic/Kbuild.asm + +generic-y	+= siginfo.h diff --git a/arch/score/include/uapi/asm/siginfo.h b/arch/score/include/uapi/asm/siginfo.h deleted file mode 100644 index 87ca35607a28..000000000000 --- a/arch/score/include/uapi/asm/siginfo.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASM_SCORE_SIGINFO_H -#define _ASM_SCORE_SIGINFO_H - -#include <asm-generic/siginfo.h> - -#endif /* _ASM_SCORE_SIGINFO_H */ diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig index 4e21949593cf..3554fcaa023b 100644 --- a/arch/sh/boards/Kconfig +++ b/arch/sh/boards/Kconfig @@ -10,7 +10,7 @@ config SH_DEVICE_TREE  	bool "Board Described by Device Tree"  	select OF  	select OF_EARLY_FLATTREE -	select CLKSRC_OF +	select TIMER_OF  	select COMMON_CLK  	select GENERIC_CALIBRATE_DELAY  	help diff --git a/arch/sh/boards/of-generic.c b/arch/sh/boards/of-generic.c index 1fb6d5714bae..4feb7c86f4ac 100644 --- a/arch/sh/boards/of-generic.c +++ b/arch/sh/boards/of-generic.c @@ -119,7 +119,7 @@ static void __init sh_of_mem_reserve(void)  static void __init sh_of_time_init(void)  {  	pr_info("SH generic board support: scanning for clocksource devices\n"); -	clocksource_probe(); +	timer_probe();  }  static void __init sh_of_setup(char **cmdline_p) diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild index cf2a75063b53..590c91ae7541 100644 --- a/arch/sh/include/asm/Kbuild +++ b/arch/sh/include/asm/Kbuild @@ -29,7 +29,6 @@ generic-y += rwsem.h  generic-y += sembuf.h  generic-y += serial.h  generic-y += shmbuf.h -generic-y += siginfo.h  generic-y += sizes.h  generic-y += socket.h  generic-y += statfs.h diff --git a/arch/sh/include/uapi/asm/Kbuild b/arch/sh/include/uapi/asm/Kbuild index b15bf6bc0e94..b55fc2ae1e8c 100644 --- a/arch/sh/include/uapi/asm/Kbuild +++ b/arch/sh/include/uapi/asm/Kbuild @@ -1,2 +1,4 @@  # UAPI Header export list  include include/uapi/asm-generic/Kbuild.asm + +generic-y += siginfo.h diff --git a/arch/sparc/include/asm/siginfo.h b/arch/sparc/include/asm/siginfo.h deleted file mode 100644 index 48c34c19f810..000000000000 --- a/arch/sparc/include/asm/siginfo.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef __SPARC_SIGINFO_H -#define __SPARC_SIGINFO_H - -#include <uapi/asm/siginfo.h> - - -#ifdef CONFIG_COMPAT - -struct compat_siginfo; - -#endif /* CONFIG_COMPAT */ - -#endif /* !(__SPARC_SIGINFO_H) */ diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild index e9ad511c1043..7a53a55341de 100644 --- a/arch/unicore32/include/asm/Kbuild +++ b/arch/unicore32/include/asm/Kbuild @@ -44,7 +44,6 @@ generic-y += serial.h  generic-y += setup.h  generic-y += shmbuf.h  generic-y += shmparam.h -generic-y += siginfo.h  generic-y += signal.h  generic-y += sizes.h  generic-y += socket.h diff --git a/arch/unicore32/include/uapi/asm/Kbuild b/arch/unicore32/include/uapi/asm/Kbuild index 13a97aa2285f..1c44d3b3eba0 100644 --- a/arch/unicore32/include/uapi/asm/Kbuild +++ b/arch/unicore32/include/uapi/asm/Kbuild @@ -2,3 +2,4 @@  include include/uapi/asm-generic/Kbuild.asm  generic-y += kvm_para.h +generic-y += siginfo.h diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild index cc23e9ecc6bb..30f6290109d4 100644 --- a/arch/xtensa/include/asm/Kbuild +++ b/arch/xtensa/include/asm/Kbuild @@ -25,7 +25,6 @@ generic-y += preempt.h  generic-y += resource.h  generic-y += rwsem.h  generic-y += sections.h -generic-y += siginfo.h  generic-y += statfs.h  generic-y += termios.h  generic-y += topology.h diff --git a/arch/xtensa/include/uapi/asm/Kbuild b/arch/xtensa/include/uapi/asm/Kbuild index b15bf6bc0e94..4cb0d2f8868c 100644 --- a/arch/xtensa/include/uapi/asm/Kbuild +++ b/arch/xtensa/include/uapi/asm/Kbuild @@ -1,2 +1,3 @@  # UAPI Header export list  include include/uapi/asm-generic/Kbuild.asm +generic-y += siginfo.h diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c index 668c1056f9e4..fd524a54d2ab 100644 --- a/arch/xtensa/kernel/time.c +++ b/arch/xtensa/kernel/time.c @@ -187,7 +187,7 @@ void __init time_init(void)  	local_timer_setup(0);  	setup_irq(this_cpu_ptr(&ccount_timer)->evt.irq, &timer_irqaction);  	sched_clock_register(ccount_sched_clock_read, 32, ccount_freq); -	clocksource_probe(); +	timer_probe();  }  /* diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 31adbebf812e..2af70014ee5a 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -539,15 +539,6 @@ config HANGCHECK_TIMER  	  out to lunch past a certain margin.  It can reboot the system  	  or merely print a warning. -config MMTIMER -	tristate "MMTIMER Memory mapped RTC for SGI Altix" -	depends on IA64_GENERIC || IA64_SGI_SN2 -	depends on POSIX_TIMERS -	default y -	help -	  The mmtimer device allows direct userspace access to the -	  Altix system timer. -  config UV_MMTIMER  	tristate "UV_MMTIMER Memory mapped RTC for SGI UV"  	depends on X86_UV diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 6e6c244a66a0..53e33720818c 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -10,7 +10,6 @@ obj-$(CONFIG_VIRTIO_CONSOLE)	+= virtio_console.o  obj-$(CONFIG_RAW_DRIVER)	+= raw.o  obj-$(CONFIG_SGI_SNSC)		+= snsc.o snsc_event.o  obj-$(CONFIG_MSPEC)		+= mspec.o -obj-$(CONFIG_MMTIMER)		+= mmtimer.o  obj-$(CONFIG_UV_MMTIMER)	+= uv_mmtimer.o  obj-$(CONFIG_IBM_BSR)		+= bsr.o  obj-$(CONFIG_SGI_MBCS)		+= mbcs.o diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c deleted file mode 100644 index 0e7fcb04f01e..000000000000 --- a/drivers/char/mmtimer.c +++ /dev/null @@ -1,858 +0,0 @@ -/* - * Timer device implementation for SGI SN platforms. - * - * This file is subject to the terms and conditions of the GNU General Public - * License.  See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (c) 2001-2006 Silicon Graphics, Inc.  All rights reserved. - * - * This driver exports an API that should be supportable by any HPET or IA-PC - * multimedia timer.  The code below is currently specific to the SGI Altix - * SHub RTC, however. - * - * 11/01/01 - jbarnes - initial revision - * 9/10/04 - Christoph Lameter - remove interrupt support for kernel inclusion - * 10/1/04 - Christoph Lameter - provide posix clock CLOCK_SGI_CYCLE - * 10/13/04 - Christoph Lameter, Dimitri Sivanich - provide timer interrupt - *		support via the posix timer interface - */ - -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/ioctl.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/errno.h> -#include <linux/mm.h> -#include <linux/fs.h> -#include <linux/mmtimer.h> -#include <linux/miscdevice.h> -#include <linux/posix-timers.h> -#include <linux/interrupt.h> -#include <linux/time.h> -#include <linux/math64.h> -#include <linux/mutex.h> -#include <linux/slab.h> - -#include <linux/uaccess.h> -#include <asm/sn/addrs.h> -#include <asm/sn/intr.h> -#include <asm/sn/shub_mmr.h> -#include <asm/sn/nodepda.h> -#include <asm/sn/shubio.h> - -MODULE_AUTHOR("Jesse Barnes <[email protected]>"); -MODULE_DESCRIPTION("SGI Altix RTC Timer"); -MODULE_LICENSE("GPL"); - -/* name of the device, usually in /dev */ -#define MMTIMER_NAME "mmtimer" -#define MMTIMER_DESC "SGI Altix RTC Timer" -#define MMTIMER_VERSION "2.1" - -#define RTC_BITS 55 /* 55 bits for this implementation */ - -static struct k_clock sgi_clock; - -extern unsigned long sn_rtc_cycles_per_second; - -#define RTC_COUNTER_ADDR        ((long *)LOCAL_MMR_ADDR(SH_RTC)) - -#define rtc_time()              (*RTC_COUNTER_ADDR) - -static DEFINE_MUTEX(mmtimer_mutex); -static long mmtimer_ioctl(struct file *file, unsigned int cmd, -						unsigned long arg); -static int mmtimer_mmap(struct file *file, struct vm_area_struct *vma); - -/* - * Period in femtoseconds (10^-15 s) - */ -static unsigned long mmtimer_femtoperiod = 0; - -static const struct file_operations mmtimer_fops = { -	.owner = THIS_MODULE, -	.mmap =	mmtimer_mmap, -	.unlocked_ioctl = mmtimer_ioctl, -	.llseek = noop_llseek, -}; - -/* - * We only have comparison registers RTC1-4 currently available per - * node.  RTC0 is used by SAL. - */ -/* Check for an RTC interrupt pending */ -static int mmtimer_int_pending(int comparator) -{ -	if (HUB_L((unsigned long *)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED)) & -			SH_EVENT_OCCURRED_RTC1_INT_MASK << comparator) -		return 1; -	else -		return 0; -} - -/* Clear the RTC interrupt pending bit */ -static void mmtimer_clr_int_pending(int comparator) -{ -	HUB_S((u64 *)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED_ALIAS), -		SH_EVENT_OCCURRED_RTC1_INT_MASK << comparator); -} - -/* Setup timer on comparator RTC1 */ -static void mmtimer_setup_int_0(int cpu, u64 expires) -{ -	u64 val; - -	/* Disable interrupt */ -	HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC1_INT_ENABLE), 0UL); - -	/* Initialize comparator value */ -	HUB_S((u64 *)LOCAL_MMR_ADDR(SH_INT_CMPB), -1L); - -	/* Clear pending bit */ -	mmtimer_clr_int_pending(0); - -	val = ((u64)SGI_MMTIMER_VECTOR << SH_RTC1_INT_CONFIG_IDX_SHFT) | -		((u64)cpu_physical_id(cpu) << -			SH_RTC1_INT_CONFIG_PID_SHFT); - -	/* Set configuration */ -	HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC1_INT_CONFIG), val); - -	/* Enable RTC interrupts */ -	HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC1_INT_ENABLE), 1UL); - -	/* Initialize comparator value */ -	HUB_S((u64 *)LOCAL_MMR_ADDR(SH_INT_CMPB), expires); - - -} - -/* Setup timer on comparator RTC2 */ -static void mmtimer_setup_int_1(int cpu, u64 expires) -{ -	u64 val; - -	HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC2_INT_ENABLE), 0UL); - -	HUB_S((u64 *)LOCAL_MMR_ADDR(SH_INT_CMPC), -1L); - -	mmtimer_clr_int_pending(1); - -	val = ((u64)SGI_MMTIMER_VECTOR << SH_RTC2_INT_CONFIG_IDX_SHFT) | -		((u64)cpu_physical_id(cpu) << -			SH_RTC2_INT_CONFIG_PID_SHFT); - -	HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC2_INT_CONFIG), val); - -	HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC2_INT_ENABLE), 1UL); - -	HUB_S((u64 *)LOCAL_MMR_ADDR(SH_INT_CMPC), expires); -} - -/* Setup timer on comparator RTC3 */ -static void mmtimer_setup_int_2(int cpu, u64 expires) -{ -	u64 val; - -	HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC3_INT_ENABLE), 0UL); - -	HUB_S((u64 *)LOCAL_MMR_ADDR(SH_INT_CMPD), -1L); - -	mmtimer_clr_int_pending(2); - -	val = ((u64)SGI_MMTIMER_VECTOR << SH_RTC3_INT_CONFIG_IDX_SHFT) | -		((u64)cpu_physical_id(cpu) << -			SH_RTC3_INT_CONFIG_PID_SHFT); - -	HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC3_INT_CONFIG), val); - -	HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC3_INT_ENABLE), 1UL); - -	HUB_S((u64 *)LOCAL_MMR_ADDR(SH_INT_CMPD), expires); -} - -/* - * This function must be called with interrupts disabled and preemption off - * in order to insure that the setup succeeds in a deterministic time frame. - * It will check if the interrupt setup succeeded. - */ -static int mmtimer_setup(int cpu, int comparator, unsigned long expires, -	u64 *set_completion_time) -{ -	switch (comparator) { -	case 0: -		mmtimer_setup_int_0(cpu, expires); -		break; -	case 1: -		mmtimer_setup_int_1(cpu, expires); -		break; -	case 2: -		mmtimer_setup_int_2(cpu, expires); -		break; -	} -	/* We might've missed our expiration time */ -	*set_completion_time = rtc_time(); -	if (*set_completion_time <= expires) -		return 1; - -	/* -	 * If an interrupt is already pending then its okay -	 * if not then we failed -	 */ -	return mmtimer_int_pending(comparator); -} - -static int mmtimer_disable_int(long nasid, int comparator) -{ -	switch (comparator) { -	case 0: -		nasid == -1 ? HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC1_INT_ENABLE), -			0UL) : REMOTE_HUB_S(nasid, SH_RTC1_INT_ENABLE, 0UL); -		break; -	case 1: -		nasid == -1 ? HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC2_INT_ENABLE), -			0UL) : REMOTE_HUB_S(nasid, SH_RTC2_INT_ENABLE, 0UL); -		break; -	case 2: -		nasid == -1 ? HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC3_INT_ENABLE), -			0UL) : REMOTE_HUB_S(nasid, SH_RTC3_INT_ENABLE, 0UL); -		break; -	default: -		return -EFAULT; -	} -	return 0; -} - -#define COMPARATOR	1		/* The comparator to use */ - -#define TIMER_OFF	0xbadcabLL	/* Timer is not setup */ -#define TIMER_SET	0		/* Comparator is set for this timer */ - -#define MMTIMER_INTERVAL_RETRY_INCREMENT_DEFAULT 40 - -/* There is one of these for each timer */ -struct mmtimer { -	struct rb_node list; -	struct k_itimer *timer; -	int cpu; -}; - -struct mmtimer_node { -	spinlock_t lock ____cacheline_aligned; -	struct rb_root timer_head; -	struct rb_node *next; -	struct tasklet_struct tasklet; -}; -static struct mmtimer_node *timers; - -static unsigned mmtimer_interval_retry_increment = -	MMTIMER_INTERVAL_RETRY_INCREMENT_DEFAULT; -module_param(mmtimer_interval_retry_increment, uint, 0644); -MODULE_PARM_DESC(mmtimer_interval_retry_increment, -	"RTC ticks to add to expiration on interval retry (default 40)"); - -/* - * Add a new mmtimer struct to the node's mmtimer list. - * This function assumes the struct mmtimer_node is locked. - */ -static void mmtimer_add_list(struct mmtimer *n) -{ -	int nodeid = n->timer->it.mmtimer.node; -	unsigned long expires = n->timer->it.mmtimer.expires; -	struct rb_node **link = &timers[nodeid].timer_head.rb_node; -	struct rb_node *parent = NULL; -	struct mmtimer *x; - -	/* -	 * Find the right place in the rbtree: -	 */ -	while (*link) { -		parent = *link; -		x = rb_entry(parent, struct mmtimer, list); - -		if (expires < x->timer->it.mmtimer.expires) -			link = &(*link)->rb_left; -		else -			link = &(*link)->rb_right; -	} - -	/* -	 * Insert the timer to the rbtree and check whether it -	 * replaces the first pending timer -	 */ -	rb_link_node(&n->list, parent, link); -	rb_insert_color(&n->list, &timers[nodeid].timer_head); - -	if (!timers[nodeid].next || expires < rb_entry(timers[nodeid].next, -			struct mmtimer, list)->timer->it.mmtimer.expires) -		timers[nodeid].next = &n->list; -} - -/* - * Set the comparator for the next timer. - * This function assumes the struct mmtimer_node is locked. - */ -static void mmtimer_set_next_timer(int nodeid) -{ -	struct mmtimer_node *n = &timers[nodeid]; -	struct mmtimer *x; -	struct k_itimer *t; -	u64 expires, exp, set_completion_time; -	int i; - -restart: -	if (n->next == NULL) -		return; - -	x = rb_entry(n->next, struct mmtimer, list); -	t = x->timer; -	if (!t->it.mmtimer.incr) { -		/* Not an interval timer */ -		if (!mmtimer_setup(x->cpu, COMPARATOR, -					t->it.mmtimer.expires, -					&set_completion_time)) { -			/* Late setup, fire now */ -			tasklet_schedule(&n->tasklet); -		} -		return; -	} - -	/* Interval timer */ -	i = 0; -	expires = exp = t->it.mmtimer.expires; -	while (!mmtimer_setup(x->cpu, COMPARATOR, expires, -				&set_completion_time)) { -		int to; - -		i++; -		expires = set_completion_time + -				mmtimer_interval_retry_increment + (1 << i); -		/* Calculate overruns as we go. */ -		to = ((u64)(expires - exp) / t->it.mmtimer.incr); -		if (to) { -			t->it_overrun += to; -			t->it.mmtimer.expires += t->it.mmtimer.incr * to; -			exp = t->it.mmtimer.expires; -		} -		if (i > 20) { -			printk(KERN_ALERT "mmtimer: cannot reschedule timer\n"); -			t->it.mmtimer.clock = TIMER_OFF; -			n->next = rb_next(&x->list); -			rb_erase(&x->list, &n->timer_head); -			kfree(x); -			goto restart; -		} -	} -} - -/** - * mmtimer_ioctl - ioctl interface for /dev/mmtimer - * @file: file structure for the device - * @cmd: command to execute - * @arg: optional argument to command - * - * Executes the command specified by @cmd.  Returns 0 for success, < 0 for - * failure. - * - * Valid commands: - * - * %MMTIMER_GETOFFSET - Should return the offset (relative to the start - * of the page where the registers are mapped) for the counter in question. - * - * %MMTIMER_GETRES - Returns the resolution of the clock in femto (10^-15) - * seconds - * - * %MMTIMER_GETFREQ - Copies the frequency of the clock in Hz to the address - * specified by @arg - * - * %MMTIMER_GETBITS - Returns the number of bits in the clock's counter - * - * %MMTIMER_MMAPAVAIL - Returns 1 if the registers can be mmap'd into userspace - * - * %MMTIMER_GETCOUNTER - Gets the current value in the counter and places it - * in the address specified by @arg. - */ -static long mmtimer_ioctl(struct file *file, unsigned int cmd, -						unsigned long arg) -{ -	int ret = 0; - -	mutex_lock(&mmtimer_mutex); - -	switch (cmd) { -	case MMTIMER_GETOFFSET:	/* offset of the counter */ -		/* -		 * SN RTC registers are on their own 64k page -		 */ -		if(PAGE_SIZE <= (1 << 16)) -			ret = (((long)RTC_COUNTER_ADDR) & (PAGE_SIZE-1)) / 8; -		else -			ret = -ENOSYS; -		break; - -	case MMTIMER_GETRES: /* resolution of the clock in 10^-15 s */ -		if(copy_to_user((unsigned long __user *)arg, -				&mmtimer_femtoperiod, sizeof(unsigned long))) -			ret = -EFAULT; -		break; - -	case MMTIMER_GETFREQ: /* frequency in Hz */ -		if(copy_to_user((unsigned long __user *)arg, -				&sn_rtc_cycles_per_second, -				sizeof(unsigned long))) -			ret = -EFAULT; -		break; - -	case MMTIMER_GETBITS: /* number of bits in the clock */ -		ret = RTC_BITS; -		break; - -	case MMTIMER_MMAPAVAIL: /* can we mmap the clock into userspace? */ -		ret = (PAGE_SIZE <= (1 << 16)) ? 1 : 0; -		break; - -	case MMTIMER_GETCOUNTER: -		if(copy_to_user((unsigned long __user *)arg, -				RTC_COUNTER_ADDR, sizeof(unsigned long))) -			ret = -EFAULT; -		break; -	default: -		ret = -ENOTTY; -		break; -	} -	mutex_unlock(&mmtimer_mutex); -	return ret; -} - -/** - * mmtimer_mmap - maps the clock's registers into userspace - * @file: file structure for the device - * @vma: VMA to map the registers into - * - * Calls remap_pfn_range() to map the clock's registers into - * the calling process' address space. - */ -static int mmtimer_mmap(struct file *file, struct vm_area_struct *vma) -{ -	unsigned long mmtimer_addr; - -	if (vma->vm_end - vma->vm_start != PAGE_SIZE) -		return -EINVAL; - -	if (vma->vm_flags & VM_WRITE) -		return -EPERM; - -	if (PAGE_SIZE > (1 << 16)) -		return -ENOSYS; - -	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - -	mmtimer_addr = __pa(RTC_COUNTER_ADDR); -	mmtimer_addr &= ~(PAGE_SIZE - 1); -	mmtimer_addr &= 0xfffffffffffffffUL; - -	if (remap_pfn_range(vma, vma->vm_start, mmtimer_addr >> PAGE_SHIFT, -					PAGE_SIZE, vma->vm_page_prot)) { -		printk(KERN_ERR "remap_pfn_range failed in mmtimer.c\n"); -		return -EAGAIN; -	} - -	return 0; -} - -static struct miscdevice mmtimer_miscdev = { -	.minor = SGI_MMTIMER, -	.name = MMTIMER_NAME, -	.fops = &mmtimer_fops -}; - -static struct timespec sgi_clock_offset; -static int sgi_clock_period; - -/* - * Posix Timer Interface - */ - -static struct timespec sgi_clock_offset; -static int sgi_clock_period; - -static int sgi_clock_get(clockid_t clockid, struct timespec64 *tp) -{ -	u64 nsec; - -	nsec = rtc_time() * sgi_clock_period -			+ sgi_clock_offset.tv_nsec; -	*tp = ns_to_timespec64(nsec); -	tp->tv_sec += sgi_clock_offset.tv_sec; -	return 0; -}; - -static int sgi_clock_set(const clockid_t clockid, const struct timespec64 *tp) -{ - -	u64 nsec; -	u32 rem; - -	nsec = rtc_time() * sgi_clock_period; - -	sgi_clock_offset.tv_sec = tp->tv_sec - div_u64_rem(nsec, NSEC_PER_SEC, &rem); - -	if (rem <= tp->tv_nsec) -		sgi_clock_offset.tv_nsec = tp->tv_sec - rem; -	else { -		sgi_clock_offset.tv_nsec = tp->tv_sec + NSEC_PER_SEC - rem; -		sgi_clock_offset.tv_sec--; -	} -	return 0; -} - -/** - * mmtimer_interrupt - timer interrupt handler - * @irq: irq received - * @dev_id: device the irq came from - * - * Called when one of the comarators matches the counter, This - * routine will send signals to processes that have requested - * them. - * - * This interrupt is run in an interrupt context - * by the SHUB. It is therefore safe to locally access SHub - * registers. - */ -static irqreturn_t -mmtimer_interrupt(int irq, void *dev_id) -{ -	unsigned long expires = 0; -	int result = IRQ_NONE; -	unsigned indx = cpu_to_node(smp_processor_id()); -	struct mmtimer *base; - -	spin_lock(&timers[indx].lock); -	base = rb_entry(timers[indx].next, struct mmtimer, list); -	if (base == NULL) { -		spin_unlock(&timers[indx].lock); -		return result; -	} - -	if (base->cpu == smp_processor_id()) { -		if (base->timer) -			expires = base->timer->it.mmtimer.expires; -		/* expires test won't work with shared irqs */ -		if ((mmtimer_int_pending(COMPARATOR) > 0) || -			(expires && (expires <= rtc_time()))) { -			mmtimer_clr_int_pending(COMPARATOR); -			tasklet_schedule(&timers[indx].tasklet); -			result = IRQ_HANDLED; -		} -	} -	spin_unlock(&timers[indx].lock); -	return result; -} - -static void mmtimer_tasklet(unsigned long data) -{ -	int nodeid = data; -	struct mmtimer_node *mn = &timers[nodeid]; -	struct mmtimer *x; -	struct k_itimer *t; -	unsigned long flags; - -	/* Send signal and deal with periodic signals */ -	spin_lock_irqsave(&mn->lock, flags); -	if (!mn->next) -		goto out; - -	x = rb_entry(mn->next, struct mmtimer, list); -	t = x->timer; - -	if (t->it.mmtimer.clock == TIMER_OFF) -		goto out; - -	t->it_overrun = 0; - -	mn->next = rb_next(&x->list); -	rb_erase(&x->list, &mn->timer_head); - -	if (posix_timer_event(t, 0) != 0) -		t->it_overrun++; - -	if(t->it.mmtimer.incr) { -		t->it.mmtimer.expires += t->it.mmtimer.incr; -		mmtimer_add_list(x); -	} else { -		/* Ensure we don't false trigger in mmtimer_interrupt */ -		t->it.mmtimer.clock = TIMER_OFF; -		t->it.mmtimer.expires = 0; -		kfree(x); -	} -	/* Set comparator for next timer, if there is one */ -	mmtimer_set_next_timer(nodeid); - -	t->it_overrun_last = t->it_overrun; -out: -	spin_unlock_irqrestore(&mn->lock, flags); -} - -static int sgi_timer_create(struct k_itimer *timer) -{ -	/* Insure that a newly created timer is off */ -	timer->it.mmtimer.clock = TIMER_OFF; -	return 0; -} - -/* This does not really delete a timer. It just insures - * that the timer is not active - * - * Assumption: it_lock is already held with irq's disabled - */ -static int sgi_timer_del(struct k_itimer *timr) -{ -	cnodeid_t nodeid = timr->it.mmtimer.node; -	unsigned long irqflags; - -	spin_lock_irqsave(&timers[nodeid].lock, irqflags); -	if (timr->it.mmtimer.clock != TIMER_OFF) { -		unsigned long expires = timr->it.mmtimer.expires; -		struct rb_node *n = timers[nodeid].timer_head.rb_node; -		struct mmtimer *uninitialized_var(t); -		int r = 0; - -		timr->it.mmtimer.clock = TIMER_OFF; -		timr->it.mmtimer.expires = 0; - -		while (n) { -			t = rb_entry(n, struct mmtimer, list); -			if (t->timer == timr) -				break; - -			if (expires < t->timer->it.mmtimer.expires) -				n = n->rb_left; -			else -				n = n->rb_right; -		} - -		if (!n) { -			spin_unlock_irqrestore(&timers[nodeid].lock, irqflags); -			return 0; -		} - -		if (timers[nodeid].next == n) { -			timers[nodeid].next = rb_next(n); -			r = 1; -		} - -		rb_erase(n, &timers[nodeid].timer_head); -		kfree(t); - -		if (r) { -			mmtimer_disable_int(cnodeid_to_nasid(nodeid), -				COMPARATOR); -			mmtimer_set_next_timer(nodeid); -		} -	} -	spin_unlock_irqrestore(&timers[nodeid].lock, irqflags); -	return 0; -} - -/* Assumption: it_lock is already held with irq's disabled */ -static void sgi_timer_get(struct k_itimer *timr, struct itimerspec64 *cur_setting) -{ - -	if (timr->it.mmtimer.clock == TIMER_OFF) { -		cur_setting->it_interval.tv_nsec = 0; -		cur_setting->it_interval.tv_sec = 0; -		cur_setting->it_value.tv_nsec = 0; -		cur_setting->it_value.tv_sec =0; -		return; -	} - -	cur_setting->it_interval = ns_to_timespec64(timr->it.mmtimer.incr * sgi_clock_period); -	cur_setting->it_value = ns_to_timespec64((timr->it.mmtimer.expires - rtc_time()) * sgi_clock_period); -} - - -static int sgi_timer_set(struct k_itimer *timr, int flags, -	struct itimerspec64 *new_setting, -	struct itimerspec64 *old_setting) -{ -	unsigned long when, period, irqflags; -	int err = 0; -	cnodeid_t nodeid; -	struct mmtimer *base; -	struct rb_node *n; - -	if (old_setting) -		sgi_timer_get(timr, old_setting); - -	sgi_timer_del(timr); -	when = timespec64_to_ns(&new_setting->it_value); -	period = timespec64_to_ns(&new_setting->it_interval); - -	if (when == 0) -		/* Clear timer */ -		return 0; - -	base = kmalloc(sizeof(struct mmtimer), GFP_KERNEL); -	if (base == NULL) -		return -ENOMEM; - -	if (flags & TIMER_ABSTIME) { -		struct timespec64 n; -		unsigned long now; - -		getnstimeofday64(&n); -		now = timespec64_to_ns(&n); -		if (when > now) -			when -= now; -		else -			/* Fire the timer immediately */ -			when = 0; -	} - -	/* -	 * Convert to sgi clock period. Need to keep rtc_time() as near as possible -	 * to getnstimeofday() in order to be as faithful as possible to the time -	 * specified. -	 */ -	when = (when + sgi_clock_period - 1) / sgi_clock_period + rtc_time(); -	period = (period + sgi_clock_period - 1)  / sgi_clock_period; - -	/* -	 * We are allocating a local SHub comparator. If we would be moved to another -	 * cpu then another SHub may be local to us. Prohibit that by switching off -	 * preemption. -	 */ -	preempt_disable(); - -	nodeid =  cpu_to_node(smp_processor_id()); - -	/* Lock the node timer structure */ -	spin_lock_irqsave(&timers[nodeid].lock, irqflags); - -	base->timer = timr; -	base->cpu = smp_processor_id(); - -	timr->it.mmtimer.clock = TIMER_SET; -	timr->it.mmtimer.node = nodeid; -	timr->it.mmtimer.incr = period; -	timr->it.mmtimer.expires = when; - -	n = timers[nodeid].next; - -	/* Add the new struct mmtimer to node's timer list */ -	mmtimer_add_list(base); - -	if (timers[nodeid].next == n) { -		/* No need to reprogram comparator for now */ -		spin_unlock_irqrestore(&timers[nodeid].lock, irqflags); -		preempt_enable(); -		return err; -	} - -	/* We need to reprogram the comparator */ -	if (n) -		mmtimer_disable_int(cnodeid_to_nasid(nodeid), COMPARATOR); - -	mmtimer_set_next_timer(nodeid); - -	/* Unlock the node timer structure */ -	spin_unlock_irqrestore(&timers[nodeid].lock, irqflags); - -	preempt_enable(); - -	return err; -} - -static int sgi_clock_getres(const clockid_t which_clock, struct timespec64 *tp) -{ -	tp->tv_sec = 0; -	tp->tv_nsec = sgi_clock_period; -	return 0; -} - -static struct k_clock sgi_clock = { -	.clock_set	= sgi_clock_set, -	.clock_get	= sgi_clock_get, -	.clock_getres	= sgi_clock_getres, -	.timer_create	= sgi_timer_create, -	.timer_set	= sgi_timer_set, -	.timer_del	= sgi_timer_del, -	.timer_get	= sgi_timer_get -}; - -/** - * mmtimer_init - device initialization routine - * - * Does initial setup for the mmtimer device. - */ -static int __init mmtimer_init(void) -{ -	cnodeid_t node, maxn = -1; - -	if (!ia64_platform_is("sn2")) -		return 0; - -	/* -	 * Sanity check the cycles/sec variable -	 */ -	if (sn_rtc_cycles_per_second < 100000) { -		printk(KERN_ERR "%s: unable to determine clock frequency\n", -		       MMTIMER_NAME); -		goto out1; -	} - -	mmtimer_femtoperiod = ((unsigned long)1E15 + sn_rtc_cycles_per_second / -			       2) / sn_rtc_cycles_per_second; - -	if (request_irq(SGI_MMTIMER_VECTOR, mmtimer_interrupt, IRQF_PERCPU, MMTIMER_NAME, NULL)) { -		printk(KERN_WARNING "%s: unable to allocate interrupt.", -			MMTIMER_NAME); -		goto out1; -	} - -	if (misc_register(&mmtimer_miscdev)) { -		printk(KERN_ERR "%s: failed to register device\n", -		       MMTIMER_NAME); -		goto out2; -	} - -	/* Get max numbered node, calculate slots needed */ -	for_each_online_node(node) { -		maxn = node; -	} -	maxn++; - -	/* Allocate list of node ptrs to mmtimer_t's */ -	timers = kzalloc(sizeof(struct mmtimer_node)*maxn, GFP_KERNEL); -	if (!timers) { -		printk(KERN_ERR "%s: failed to allocate memory for device\n", -				MMTIMER_NAME); -		goto out3; -	} - -	/* Initialize struct mmtimer's for each online node */ -	for_each_online_node(node) { -		spin_lock_init(&timers[node].lock); -		tasklet_init(&timers[node].tasklet, mmtimer_tasklet, -			(unsigned long) node); -	} - -	sgi_clock_period = NSEC_PER_SEC / sn_rtc_cycles_per_second; -	posix_timers_register_clock(CLOCK_SGI_CYCLE, &sgi_clock); - -	printk(KERN_INFO "%s: v%s, %ld MHz\n", MMTIMER_DESC, MMTIMER_VERSION, -	       sn_rtc_cycles_per_second/(unsigned long)1E6); - -	return 0; - -out3: -	misc_deregister(&mmtimer_miscdev); -out2: -	free_irq(SGI_MMTIMER_VECTOR, NULL); -out1: -	return -1; -} - -module_init(mmtimer_init); diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 545d541ae20e..88818a43d6e9 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -1,22 +1,16 @@  menu "Clock Source drivers"  	depends on !ARCH_USES_GETTIMEOFFSET -config CLKSRC_OF +config TIMER_OF  	bool -	select CLKSRC_PROBE - -config CLKEVT_OF -	bool -	select CLKEVT_PROBE - -config CLKSRC_ACPI -	bool -	select CLKSRC_PROBE +	depends on GENERIC_CLOCKEVENTS +	select TIMER_PROBE -config CLKSRC_PROBE +config TIMER_ACPI  	bool +	select TIMER_PROBE -config CLKEVT_PROBE +config TIMER_PROBE  	bool  config CLKSRC_I8253 @@ -65,14 +59,14 @@ config DW_APB_TIMER  config DW_APB_TIMER_OF  	bool  	select DW_APB_TIMER -	select CLKSRC_OF +	select TIMER_OF  config FTTMR010_TIMER  	bool "Faraday Technology timer driver" if COMPILE_TEST  	depends on GENERIC_CLOCKEVENTS  	depends on HAS_IOMEM  	select CLKSRC_MMIO -	select CLKSRC_OF +	select TIMER_OF  	select MFD_SYSCON  	help  	  Enables support for the Faraday Technology timer block @@ -81,7 +75,7 @@ config FTTMR010_TIMER  config ROCKCHIP_TIMER  	bool "Rockchip timer driver" if COMPILE_TEST  	depends on ARM || ARM64 -	select CLKSRC_OF +	select TIMER_OF  	select CLKSRC_MMIO  	help  	  Enables the support for the rockchip timer driver. @@ -89,7 +83,7 @@ config ROCKCHIP_TIMER  config ARMADA_370_XP_TIMER  	bool "Armada 370 and XP timer driver" if COMPILE_TEST  	depends on ARM -	select CLKSRC_OF +	select TIMER_OF  	select CLKSRC_MMIO  	help  	  Enables the support for the Armada 370 and XP timer driver. @@ -104,7 +98,7 @@ config MESON6_TIMER  config ORION_TIMER  	bool "Orion timer driver" if COMPILE_TEST  	depends on ARM -	select CLKSRC_OF +	select TIMER_OF  	select CLKSRC_MMIO  	help  	  Enables the support for the Orion timer driver @@ -114,6 +108,7 @@ config SUN4I_TIMER  	depends on GENERIC_CLOCKEVENTS  	depends on HAS_IOMEM  	select CLKSRC_MMIO +	select TIMER_OF  	help  	  Enables support for the Sun4i timer. @@ -148,7 +143,7 @@ config ASM9260_TIMER  	bool "ASM9260 timer driver" if COMPILE_TEST  	depends on GENERIC_CLOCKEVENTS  	select CLKSRC_MMIO -	select CLKSRC_OF +	select TIMER_OF  	help  	  Enables support for the ASM9260 timer. @@ -188,13 +183,6 @@ config ATLAS7_TIMER  	help  	  Enables support for the Atlas7 timer. -config MOXART_TIMER -	bool "Moxart timer driver" if COMPILE_TEST -	depends on GENERIC_CLOCKEVENTS -	select CLKSRC_MMIO -	help -	  Enables support for the Moxart timer. -  config MXS_TIMER  	bool "Mxs timer driver" if COMPILE_TEST  	depends on GENERIC_CLOCKEVENTS @@ -261,21 +249,21 @@ config CLKSRC_LPC32XX  	depends on GENERIC_CLOCKEVENTS && HAS_IOMEM  	depends on ARM  	select CLKSRC_MMIO -	select CLKSRC_OF +	select TIMER_OF  	help  	  Support for the LPC32XX clocksource.  config CLKSRC_PISTACHIO  	bool "Clocksource for Pistachio SoC" if COMPILE_TEST  	depends on HAS_IOMEM -	select CLKSRC_OF +	select TIMER_OF  	help  	  Enables the clocksource for the Pistachio SoC.  config CLKSRC_TI_32K  	bool "Texas Instruments 32.768 Hz Clocksource" if COMPILE_TEST  	depends on GENERIC_SCHED_CLOCK -	select CLKSRC_OF if OF +	select TIMER_OF if OF  	help  	  This option enables support for Texas Instruments 32.768 Hz clocksource  	  available on many OMAP-like platforms. @@ -284,7 +272,7 @@ config CLKSRC_NPS  	bool "NPS400 clocksource driver" if COMPILE_TEST  	depends on !PHYS_ADDR_T_64BIT  	select CLKSRC_MMIO -	select CLKSRC_OF if OF +	select TIMER_OF if OF  	help  	  NPS400 clocksource support.  	  Got 64 bit counter with update rate up to 1000MHz. @@ -299,12 +287,12 @@ config CLKSRC_MPS2  	bool "Clocksource for MPS2 SoCs" if COMPILE_TEST  	depends on GENERIC_SCHED_CLOCK  	select CLKSRC_MMIO -	select CLKSRC_OF +	select TIMER_OF  config ARC_TIMERS  	bool "Support for 32-bit TIMERn counters in ARC Cores" if COMPILE_TEST  	depends on GENERIC_CLOCKEVENTS -	select CLKSRC_OF +	select TIMER_OF  	help  	  These are legacy 32-bit TIMER0 and TIMER1 counters found on all ARC cores  	  (ARC700 as well as ARC HS38). @@ -314,7 +302,7 @@ config ARC_TIMERS_64BIT  	bool "Support for 64-bit counters in ARC HS38 cores" if COMPILE_TEST  	depends on GENERIC_CLOCKEVENTS  	depends on ARC_TIMERS -	select CLKSRC_OF +	select TIMER_OF  	help  	  This enables 2 different 64-bit timers: RTC (for UP) and GFRC (for SMP)  	  RTC is implemented inside the core, while GFRC sits outside the core in @@ -323,8 +311,8 @@ config ARC_TIMERS_64BIT  config ARM_ARCH_TIMER  	bool -	select CLKSRC_OF if OF -	select CLKSRC_ACPI if ACPI +	select TIMER_OF if OF +	select TIMER_ACPI if ACPI  config ARM_ARCH_TIMER_EVTSTREAM  	bool "Enable ARM architected timer event stream generation by default" @@ -381,7 +369,7 @@ config ARM64_ERRATUM_858921  config ARM_GLOBAL_TIMER  	bool "Support for the ARM global timer" if COMPILE_TEST -	select CLKSRC_OF if OF +	select TIMER_OF if OF  	depends on ARM  	help  	  This options enables support for the ARM global timer unit @@ -390,7 +378,7 @@ config ARM_TIMER_SP804  	bool "Support for Dual Timer SP804 module"  	depends on GENERIC_SCHED_CLOCK && CLKDEV_LOOKUP  	select CLKSRC_MMIO -	select CLKSRC_OF if OF +	select TIMER_OF if OF  config CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK  	bool @@ -401,19 +389,19 @@ config CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK  config ARMV7M_SYSTICK  	bool "Support for the ARMv7M system time" if COMPILE_TEST -	select CLKSRC_OF if OF +	select TIMER_OF if OF  	select CLKSRC_MMIO  	help  	  This options enables support for the ARMv7M system timer unit  config ATMEL_PIT -	select CLKSRC_OF if OF +	select TIMER_OF if OF  	def_bool SOC_AT91SAM9 || SOC_SAMA5  config ATMEL_ST  	bool "Atmel ST timer support" if COMPILE_TEST  	depends on GENERIC_CLOCKEVENTS -	select CLKSRC_OF +	select TIMER_OF  	select MFD_SYSCON  	help  	  Support for the Atmel ST timer. @@ -456,7 +444,7 @@ config VF_PIT_TIMER  config OXNAS_RPS_TIMER  	bool "Oxford Semiconductor OXNAS RPS Timers driver" if COMPILE_TEST  	depends on GENERIC_CLOCKEVENTS -	select CLKSRC_OF +	select TIMER_OF  	select CLKSRC_MMIO  	help  	  This enables support for the Oxford Semiconductor OXNAS RPS timers. @@ -467,7 +455,7 @@ config SYS_SUPPORTS_SH_CMT  config MTK_TIMER  	bool "Mediatek timer driver" if COMPILE_TEST  	depends on GENERIC_CLOCKEVENTS && HAS_IOMEM -	select CLKSRC_OF +	select TIMER_OF  	select CLKSRC_MMIO  	help  	  Support for Mediatek timer driver. @@ -540,7 +528,7 @@ config EM_TIMER_STI  config CLKSRC_QCOM  	bool "Qualcomm MSM timer" if COMPILE_TEST  	depends on ARM -	select CLKSRC_OF +	select TIMER_OF  	help  	  This enables the clocksource and the per CPU clockevent driver for the  	  Qualcomm SoCs. @@ -548,7 +536,7 @@ config CLKSRC_QCOM  config CLKSRC_VERSATILE  	bool "ARM Versatile (Express) reference platforms clock source" if COMPILE_TEST  	depends on GENERIC_SCHED_CLOCK && !ARCH_USES_GETTIMEOFFSET -	select CLKSRC_OF +	select TIMER_OF  	default y if MFD_VEXPRESS_SYSREG  	help  	  This option enables clock source based on free running @@ -559,12 +547,12 @@ config CLKSRC_VERSATILE  config CLKSRC_MIPS_GIC  	bool  	depends on MIPS_GIC -	select CLKSRC_OF +	select TIMER_OF  config CLKSRC_TANGO_XTAL  	bool "Clocksource for Tango SoC" if COMPILE_TEST  	depends on ARM -	select CLKSRC_OF +	select TIMER_OF  	select CLKSRC_MMIO  	help  	  This enables the clocksource for Tango SoC @@ -605,7 +593,7 @@ config CLKSRC_IMX_GPT  config CLKSRC_ST_LPC  	bool "Low power clocksource found in the LPC" if COMPILE_TEST -	select CLKSRC_OF if OF +	select TIMER_OF if OF  	depends on HAS_IOMEM  	select CLKSRC_MMIO  	help diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index 2b5b56a6f00f..72bfd001cfbb 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -1,5 +1,5 @@ -obj-$(CONFIG_CLKSRC_PROBE)	+= clksrc-probe.o -obj-$(CONFIG_CLKEVT_PROBE)	+= clkevt-probe.o +obj-$(CONFIG_TIMER_OF)		+= timer-of.o +obj-$(CONFIG_TIMER_PROBE)	+= timer-probe.o  obj-$(CONFIG_ATMEL_PIT)		+= timer-atmel-pit.o  obj-$(CONFIG_ATMEL_ST)		+= timer-atmel-st.o  obj-$(CONFIG_ATMEL_TCB_CLKSRC)	+= tcb_clksrc.o @@ -26,7 +26,6 @@ obj-$(CONFIG_ORION_TIMER)	+= time-orion.o  obj-$(CONFIG_BCM2835_TIMER)	+= bcm2835_timer.o  obj-$(CONFIG_CLPS711X_TIMER)	+= clps711x-timer.o  obj-$(CONFIG_ATLAS7_TIMER)	+= timer-atlas7.o -obj-$(CONFIG_MOXART_TIMER)	+= moxart_timer.o  obj-$(CONFIG_MXS_TIMER)		+= mxs_timer.o  obj-$(CONFIG_CLKSRC_PXA)	+= pxa_timer.o  obj-$(CONFIG_PRIMA2_TIMER)	+= timer-prima2.o diff --git a/drivers/clocksource/arc_timer.c b/drivers/clocksource/arc_timer.c index 21649733827d..4927355f9cbe 100644 --- a/drivers/clocksource/arc_timer.c +++ b/drivers/clocksource/arc_timer.c @@ -99,7 +99,7 @@ static int __init arc_cs_setup_gfrc(struct device_node *node)  	return clocksource_register_hz(&arc_counter_gfrc, arc_timer_freq);  } -CLOCKSOURCE_OF_DECLARE(arc_gfrc, "snps,archs-timer-gfrc", arc_cs_setup_gfrc); +TIMER_OF_DECLARE(arc_gfrc, "snps,archs-timer-gfrc", arc_cs_setup_gfrc);  #define AUX_RTC_CTRL	0x103  #define AUX_RTC_LOW	0x104 @@ -158,7 +158,7 @@ static int __init arc_cs_setup_rtc(struct device_node *node)  	return clocksource_register_hz(&arc_counter_rtc, arc_timer_freq);  } -CLOCKSOURCE_OF_DECLARE(arc_rtc, "snps,archs-timer-rtc", arc_cs_setup_rtc); +TIMER_OF_DECLARE(arc_rtc, "snps,archs-timer-rtc", arc_cs_setup_rtc);  #endif @@ -333,4 +333,4 @@ static int __init arc_of_timer_init(struct device_node *np)  	return ret;  } -CLOCKSOURCE_OF_DECLARE(arc_clkevt, "snps,arc-timer", arc_of_timer_init); +TIMER_OF_DECLARE(arc_clkevt, "snps,arc-timer", arc_of_timer_init); diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 8b5c30062d99..aae87c4c546e 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -1194,8 +1194,8 @@ static int __init arch_timer_of_init(struct device_node *np)  	return arch_timer_common_init();  } -CLOCKSOURCE_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", arch_timer_of_init); -CLOCKSOURCE_OF_DECLARE(armv8_arch_timer, "arm,armv8-timer", arch_timer_of_init); +TIMER_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", arch_timer_of_init); +TIMER_OF_DECLARE(armv8_arch_timer, "arm,armv8-timer", arch_timer_of_init);  static u32 __init  arch_timer_mem_frame_get_cntfrq(struct arch_timer_mem_frame *frame) @@ -1382,7 +1382,7 @@ out:  	kfree(timer_mem);  	return ret;  } -CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem", +TIMER_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem",  		       arch_timer_mem_of_init);  #ifdef CONFIG_ACPI_GTDT @@ -1516,5 +1516,5 @@ static int __init arch_timer_acpi_init(struct acpi_table_header *table)  	return arch_timer_common_init();  } -CLOCKSOURCE_ACPI_DECLARE(arch_timer, ACPI_SIG_GTDT, arch_timer_acpi_init); +TIMER_ACPI_DECLARE(arch_timer, ACPI_SIG_GTDT, arch_timer_acpi_init);  #endif diff --git a/drivers/clocksource/arm_global_timer.c b/drivers/clocksource/arm_global_timer.c index 123ed20ac2ff..095bb965f621 100644 --- a/drivers/clocksource/arm_global_timer.c +++ b/drivers/clocksource/arm_global_timer.c @@ -339,5 +339,5 @@ out_unmap:  }  /* Only tested on r2p2 and r3p0  */ -CLOCKSOURCE_OF_DECLARE(arm_gt, "arm,cortex-a9-global-timer", +TIMER_OF_DECLARE(arm_gt, "arm,cortex-a9-global-timer",  			global_timer_of_register); diff --git a/drivers/clocksource/armv7m_systick.c b/drivers/clocksource/armv7m_systick.c index a315491b7047..ac046d6fb0bf 100644 --- a/drivers/clocksource/armv7m_systick.c +++ b/drivers/clocksource/armv7m_systick.c @@ -82,5 +82,5 @@ out_unmap:  	return ret;  } -CLOCKSOURCE_OF_DECLARE(arm_systick, "arm,armv7m-systick", +TIMER_OF_DECLARE(arm_systick, "arm,armv7m-systick",  			system_timer_of_register); diff --git a/drivers/clocksource/asm9260_timer.c b/drivers/clocksource/asm9260_timer.c index c6780830b8ac..38cd2feb87c4 100644 --- a/drivers/clocksource/asm9260_timer.c +++ b/drivers/clocksource/asm9260_timer.c @@ -238,5 +238,5 @@ static int __init asm9260_timer_init(struct device_node *np)  	return 0;  } -CLOCKSOURCE_OF_DECLARE(asm9260_timer, "alphascale,asm9260-timer", +TIMER_OF_DECLARE(asm9260_timer, "alphascale,asm9260-timer",  		asm9260_timer_init); diff --git a/drivers/clocksource/bcm2835_timer.c b/drivers/clocksource/bcm2835_timer.c index dce44307469e..82828d3a4739 100644 --- a/drivers/clocksource/bcm2835_timer.c +++ b/drivers/clocksource/bcm2835_timer.c @@ -148,5 +148,5 @@ err_iounmap:  	iounmap(base);  	return ret;  } -CLOCKSOURCE_OF_DECLARE(bcm2835, "brcm,bcm2835-system-timer", +TIMER_OF_DECLARE(bcm2835, "brcm,bcm2835-system-timer",  			bcm2835_timer_init); diff --git a/drivers/clocksource/bcm_kona_timer.c b/drivers/clocksource/bcm_kona_timer.c index fda5e1476638..5c40be9880f5 100644 --- a/drivers/clocksource/bcm_kona_timer.c +++ b/drivers/clocksource/bcm_kona_timer.c @@ -198,9 +198,9 @@ static int __init kona_timer_init(struct device_node *node)  	return 0;  } -CLOCKSOURCE_OF_DECLARE(brcm_kona, "brcm,kona-timer", kona_timer_init); +TIMER_OF_DECLARE(brcm_kona, "brcm,kona-timer", kona_timer_init);  /*   * bcm,kona-timer is deprecated by brcm,kona-timer   * being kept here for driver compatibility   */ -CLOCKSOURCE_OF_DECLARE(bcm_kona, "bcm,kona-timer", kona_timer_init); +TIMER_OF_DECLARE(bcm_kona, "bcm,kona-timer", kona_timer_init); diff --git a/drivers/clocksource/cadence_ttc_timer.c b/drivers/clocksource/cadence_ttc_timer.c index 8e64b8460f11..29d51755e18b 100644 --- a/drivers/clocksource/cadence_ttc_timer.c +++ b/drivers/clocksource/cadence_ttc_timer.c @@ -540,4 +540,4 @@ static int __init ttc_timer_init(struct device_node *timer)  	return 0;  } -CLOCKSOURCE_OF_DECLARE(ttc, "cdns,ttc", ttc_timer_init); +TIMER_OF_DECLARE(ttc, "cdns,ttc", ttc_timer_init); diff --git a/drivers/clocksource/clkevt-probe.c b/drivers/clocksource/clkevt-probe.c deleted file mode 100644 index eb89b502acbd..000000000000 --- a/drivers/clocksource/clkevt-probe.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2016, Linaro Ltd.  All rights reserved. - * Daniel Lezcano <[email protected]> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program.  If not, see <http://www.gnu.org/licenses/>. - */ - -#include <linux/init.h> -#include <linux/of.h> -#include <linux/clockchips.h> - -extern struct of_device_id __clkevt_of_table[]; - -static const struct of_device_id __clkevt_of_table_sentinel -	__used __section(__clkevt_of_table_end); - -int __init clockevent_probe(void) -{ -	struct device_node *np; -	const struct of_device_id *match; -	of_init_fn_1_ret init_func; -	int ret, clockevents = 0; - -	for_each_matching_node_and_match(np, __clkevt_of_table, &match) { -		if (!of_device_is_available(np)) -			continue; - -		init_func = match->data; - -		ret = init_func(np); -		if (ret) { -			pr_warn("Failed to initialize '%s' (%d)\n", -				np->name, ret); -			continue; -		} - -		clockevents++; -	} - -	if (!clockevents) { -		pr_crit("%s: no matching clockevent found\n", __func__); -		return -ENODEV; -	} - -	return 0; -} diff --git a/drivers/clocksource/clksrc-dbx500-prcmu.c b/drivers/clocksource/clksrc-dbx500-prcmu.c index c69e2772658d..c1b96dc5f444 100644 --- a/drivers/clocksource/clksrc-dbx500-prcmu.c +++ b/drivers/clocksource/clksrc-dbx500-prcmu.c @@ -86,5 +86,5 @@ static int __init clksrc_dbx500_prcmu_init(struct device_node *node)  #endif  	return clocksource_register_hz(&clocksource_dbx500_prcmu, RATE_32K);  } -CLOCKSOURCE_OF_DECLARE(dbx500_prcmu, "stericsson,db8500-prcmu-timer-4", +TIMER_OF_DECLARE(dbx500_prcmu, "stericsson,db8500-prcmu-timer-4",  		       clksrc_dbx500_prcmu_init); diff --git a/drivers/clocksource/clksrc_st_lpc.c b/drivers/clocksource/clksrc_st_lpc.c index 03cc49217bb4..a1d01ebb81f5 100644 --- a/drivers/clocksource/clksrc_st_lpc.c +++ b/drivers/clocksource/clksrc_st_lpc.c @@ -132,4 +132,4 @@ static int __init st_clksrc_of_register(struct device_node *np)  	return ret;  } -CLOCKSOURCE_OF_DECLARE(ddata, "st,stih407-lpc", st_clksrc_of_register); +TIMER_OF_DECLARE(ddata, "st,stih407-lpc", st_clksrc_of_register); diff --git a/drivers/clocksource/clps711x-timer.c b/drivers/clocksource/clps711x-timer.c index 24db6d605549..a8dd80576c95 100644 --- a/drivers/clocksource/clps711x-timer.c +++ b/drivers/clocksource/clps711x-timer.c @@ -103,7 +103,7 @@ void __init clps711x_clksrc_init(void __iomem *tc1_base, void __iomem *tc2_base,  	BUG_ON(_clps711x_clkevt_init(tc2, tc2_base, irq));  } -#ifdef CONFIG_CLKSRC_OF +#ifdef CONFIG_TIMER_OF  static int __init clps711x_timer_init(struct device_node *np)  {  	unsigned int irq = irq_of_parse_and_map(np, 0); @@ -119,5 +119,5 @@ static int __init clps711x_timer_init(struct device_node *np)  		return -EINVAL;  	}  } -CLOCKSOURCE_OF_DECLARE(clps711x, "cirrus,ep7209-timer", clps711x_timer_init); +TIMER_OF_DECLARE(clps711x, "cirrus,ep7209-timer", clps711x_timer_init);  #endif diff --git a/drivers/clocksource/dw_apb_timer_of.c b/drivers/clocksource/dw_apb_timer_of.c index aee6c0d39a7c..69866cd8f4bb 100644 --- a/drivers/clocksource/dw_apb_timer_of.c +++ b/drivers/clocksource/dw_apb_timer_of.c @@ -167,7 +167,7 @@ static int __init dw_apb_timer_init(struct device_node *timer)  	return 0;  } -CLOCKSOURCE_OF_DECLARE(pc3x2_timer, "picochip,pc3x2-timer", dw_apb_timer_init); -CLOCKSOURCE_OF_DECLARE(apb_timer_osc, "snps,dw-apb-timer-osc", dw_apb_timer_init); -CLOCKSOURCE_OF_DECLARE(apb_timer_sp, "snps,dw-apb-timer-sp", dw_apb_timer_init); -CLOCKSOURCE_OF_DECLARE(apb_timer, "snps,dw-apb-timer", dw_apb_timer_init); +TIMER_OF_DECLARE(pc3x2_timer, "picochip,pc3x2-timer", dw_apb_timer_init); +TIMER_OF_DECLARE(apb_timer_osc, "snps,dw-apb-timer-osc", dw_apb_timer_init); +TIMER_OF_DECLARE(apb_timer_sp, "snps,dw-apb-timer-sp", dw_apb_timer_init); +TIMER_OF_DECLARE(apb_timer, "snps,dw-apb-timer", dw_apb_timer_init); diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c index 670ff0f25b67..7a244b681876 100644 --- a/drivers/clocksource/exynos_mct.c +++ b/drivers/clocksource/exynos_mct.c @@ -610,5 +610,5 @@ static int __init mct_init_ppi(struct device_node *np)  {  	return mct_init_dt(np, MCT_INT_PPI);  } -CLOCKSOURCE_OF_DECLARE(exynos4210, "samsung,exynos4210-mct", mct_init_spi); -CLOCKSOURCE_OF_DECLARE(exynos4412, "samsung,exynos4412-mct", mct_init_ppi); +TIMER_OF_DECLARE(exynos4210, "samsung,exynos4210-mct", mct_init_spi); +TIMER_OF_DECLARE(exynos4412, "samsung,exynos4412-mct", mct_init_ppi); diff --git a/drivers/clocksource/fsl_ftm_timer.c b/drivers/clocksource/fsl_ftm_timer.c index 738515b89073..3ee7e6fea621 100644 --- a/drivers/clocksource/fsl_ftm_timer.c +++ b/drivers/clocksource/fsl_ftm_timer.c @@ -329,13 +329,13 @@ static int __init ftm_timer_init(struct device_node *np)  	priv->clkevt_base = of_iomap(np, 0);  	if (!priv->clkevt_base) {  		pr_err("ftm: unable to map event timer registers\n"); -		goto err; +		goto err_clkevt;  	}  	priv->clksrc_base = of_iomap(np, 1);  	if (!priv->clksrc_base) {  		pr_err("ftm: unable to map source timer registers\n"); -		goto err; +		goto err_clksrc;  	}  	ret = -EINVAL; @@ -366,7 +366,11 @@ static int __init ftm_timer_init(struct device_node *np)  	return 0;  err: +	iounmap(priv->clksrc_base); +err_clksrc: +	iounmap(priv->clkevt_base); +err_clkevt:  	kfree(priv);  	return ret;  } -CLOCKSOURCE_OF_DECLARE(flextimer, "fsl,ftm-timer", ftm_timer_init); +TIMER_OF_DECLARE(flextimer, "fsl,ftm-timer", ftm_timer_init); diff --git a/drivers/clocksource/h8300_timer16.c b/drivers/clocksource/h8300_timer16.c index 5b27fb9997c2..dfbd4f8051cb 100644 --- a/drivers/clocksource/h8300_timer16.c +++ b/drivers/clocksource/h8300_timer16.c @@ -187,5 +187,5 @@ free_clk:  	return ret;  } -CLOCKSOURCE_OF_DECLARE(h8300_16bit, "renesas,16bit-timer", +TIMER_OF_DECLARE(h8300_16bit, "renesas,16bit-timer",  			   h8300_16timer_init); diff --git a/drivers/clocksource/h8300_timer8.c b/drivers/clocksource/h8300_timer8.c index 804c489531d6..f6ffb0cef091 100644 --- a/drivers/clocksource/h8300_timer8.c +++ b/drivers/clocksource/h8300_timer8.c @@ -207,4 +207,4 @@ free_clk:  	return ret;  } -CLOCKSOURCE_OF_DECLARE(h8300_8bit, "renesas,8bit-timer", h8300_8timer_init); +TIMER_OF_DECLARE(h8300_8bit, "renesas,8bit-timer", h8300_8timer_init); diff --git a/drivers/clocksource/h8300_tpu.c b/drivers/clocksource/h8300_tpu.c index 72e1cf2b3096..45a8d17dac1e 100644 --- a/drivers/clocksource/h8300_tpu.c +++ b/drivers/clocksource/h8300_tpu.c @@ -154,4 +154,4 @@ free_clk:  	return ret;  } -CLOCKSOURCE_OF_DECLARE(h8300_tpu, "renesas,tpu", h8300_tpu_init); +TIMER_OF_DECLARE(h8300_tpu, "renesas,tpu", h8300_tpu_init); diff --git a/drivers/clocksource/jcore-pit.c b/drivers/clocksource/jcore-pit.c index 7c61226f4359..5d3d88e0fc8c 100644 --- a/drivers/clocksource/jcore-pit.c +++ b/drivers/clocksource/jcore-pit.c @@ -246,4 +246,4 @@ static int __init jcore_pit_init(struct device_node *node)  	return 0;  } -CLOCKSOURCE_OF_DECLARE(jcore_pit, "jcore,pit", jcore_pit_init); +TIMER_OF_DECLARE(jcore_pit, "jcore,pit", jcore_pit_init); diff --git a/drivers/clocksource/meson6_timer.c b/drivers/clocksource/meson6_timer.c index 39d21f693a33..92f20991a937 100644 --- a/drivers/clocksource/meson6_timer.c +++ b/drivers/clocksource/meson6_timer.c @@ -174,5 +174,5 @@ static int __init meson6_timer_init(struct device_node *node)  					1, 0xfffe);  	return 0;  } -CLOCKSOURCE_OF_DECLARE(meson6, "amlogic,meson6-timer", +TIMER_OF_DECLARE(meson6, "amlogic,meson6-timer",  		       meson6_timer_init); diff --git a/drivers/clocksource/mips-gic-timer.c b/drivers/clocksource/mips-gic-timer.c index 3f52ee219923..17b861ea2626 100644 --- a/drivers/clocksource/mips-gic-timer.c +++ b/drivers/clocksource/mips-gic-timer.c @@ -167,10 +167,11 @@ static int __init gic_clocksource_of_init(struct device_node *node)  	clk = of_clk_get(node, 0);  	if (!IS_ERR(clk)) { -		if (clk_prepare_enable(clk) < 0) { +		ret = clk_prepare_enable(clk); +		if (ret < 0) {  			pr_err("GIC failed to enable clock\n");  			clk_put(clk); -			return PTR_ERR(clk); +			return ret;  		}  		gic_frequency = clk_get_rate(clk); @@ -200,5 +201,5 @@ static int __init gic_clocksource_of_init(struct device_node *node)  	return 0;  } -CLOCKSOURCE_OF_DECLARE(mips_gic_timer, "mti,gic-timer", +TIMER_OF_DECLARE(mips_gic_timer, "mti,gic-timer",  		       gic_clocksource_of_init); diff --git a/drivers/clocksource/moxart_timer.c b/drivers/clocksource/moxart_timer.c deleted file mode 100644 index 7f3430654fbd..000000000000 --- a/drivers/clocksource/moxart_timer.c +++ /dev/null @@ -1,256 +0,0 @@ -/* - * MOXA ART SoCs timer handling. - * - * Copyright (C) 2013 Jonas Jensen - * - * Jonas Jensen <[email protected]> - * - * This file is licensed under the terms of the GNU General Public - * License version 2.  This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include <linux/clk.h> -#include <linux/clockchips.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/irqreturn.h> -#include <linux/of.h> -#include <linux/of_address.h> -#include <linux/of_irq.h> -#include <linux/io.h> -#include <linux/clocksource.h> -#include <linux/bitops.h> -#include <linux/slab.h> - -#define TIMER1_BASE		0x00 -#define TIMER2_BASE		0x10 -#define TIMER3_BASE		0x20 - -#define REG_COUNT		0x0 /* writable */ -#define REG_LOAD		0x4 -#define REG_MATCH1		0x8 -#define REG_MATCH2		0xC - -#define TIMER_CR		0x30 -#define TIMER_INTR_STATE	0x34 -#define TIMER_INTR_MASK		0x38 - -/* - * Moxart TIMER_CR flags: - * - * MOXART_CR_*_CLOCK	0: PCLK, 1: EXT1CLK - * MOXART_CR_*_INT	overflow interrupt enable bit - */ -#define MOXART_CR_1_ENABLE	BIT(0) -#define MOXART_CR_1_CLOCK	BIT(1) -#define MOXART_CR_1_INT	BIT(2) -#define MOXART_CR_2_ENABLE	BIT(3) -#define MOXART_CR_2_CLOCK	BIT(4) -#define MOXART_CR_2_INT	BIT(5) -#define MOXART_CR_3_ENABLE	BIT(6) -#define MOXART_CR_3_CLOCK	BIT(7) -#define MOXART_CR_3_INT	BIT(8) -#define MOXART_CR_COUNT_UP	BIT(9) - -#define MOXART_TIMER1_ENABLE	(MOXART_CR_2_ENABLE | MOXART_CR_1_ENABLE) -#define MOXART_TIMER1_DISABLE	(MOXART_CR_2_ENABLE) - -/* - * The ASpeed variant of the IP block has a different layout - * for the control register - */ -#define ASPEED_CR_1_ENABLE	BIT(0) -#define ASPEED_CR_1_CLOCK	BIT(1) -#define ASPEED_CR_1_INT		BIT(2) -#define ASPEED_CR_2_ENABLE	BIT(4) -#define ASPEED_CR_2_CLOCK	BIT(5) -#define ASPEED_CR_2_INT		BIT(6) -#define ASPEED_CR_3_ENABLE	BIT(8) -#define ASPEED_CR_3_CLOCK	BIT(9) -#define ASPEED_CR_3_INT		BIT(10) - -#define ASPEED_TIMER1_ENABLE   (ASPEED_CR_2_ENABLE | ASPEED_CR_1_ENABLE) -#define ASPEED_TIMER1_DISABLE  (ASPEED_CR_2_ENABLE) - -struct moxart_timer { -	void __iomem *base; -	unsigned int t1_disable_val; -	unsigned int t1_enable_val; -	unsigned int count_per_tick; -	struct clock_event_device clkevt; -}; - -static inline struct moxart_timer *to_moxart(struct clock_event_device *evt) -{ -	return container_of(evt, struct moxart_timer, clkevt); -} - -static inline void moxart_disable(struct clock_event_device *evt) -{ -	struct moxart_timer *timer = to_moxart(evt); - -	writel(timer->t1_disable_val, timer->base + TIMER_CR); -} - -static inline void moxart_enable(struct clock_event_device *evt) -{ -	struct moxart_timer *timer = to_moxart(evt); - -	writel(timer->t1_enable_val, timer->base + TIMER_CR); -} - -static int moxart_shutdown(struct clock_event_device *evt) -{ -	moxart_disable(evt); -	return 0; -} - -static int moxart_set_oneshot(struct clock_event_device *evt) -{ -	moxart_disable(evt); -	writel(~0, to_moxart(evt)->base + TIMER1_BASE + REG_LOAD); -	return 0; -} - -static int moxart_set_periodic(struct clock_event_device *evt) -{ -	struct moxart_timer *timer = to_moxart(evt); - -	moxart_disable(evt); -	writel(timer->count_per_tick, timer->base + TIMER1_BASE + REG_LOAD); -	writel(0, timer->base + TIMER1_BASE + REG_MATCH1); -	moxart_enable(evt); -	return 0; -} - -static int moxart_clkevt_next_event(unsigned long cycles, -				    struct clock_event_device *evt) -{ -	struct moxart_timer *timer = to_moxart(evt); -	u32 u; - -	moxart_disable(evt); - -	u = readl(timer->base + TIMER1_BASE + REG_COUNT) - cycles; -	writel(u, timer->base + TIMER1_BASE + REG_MATCH1); - -	moxart_enable(evt); - -	return 0; -} - -static irqreturn_t moxart_timer_interrupt(int irq, void *dev_id) -{ -	struct clock_event_device *evt = dev_id; -	evt->event_handler(evt); -	return IRQ_HANDLED; -} - -static int __init moxart_timer_init(struct device_node *node) -{ -	int ret, irq; -	unsigned long pclk; -	struct clk *clk; -	struct moxart_timer *timer; - -	timer = kzalloc(sizeof(*timer), GFP_KERNEL); -	if (!timer) -		return -ENOMEM; - -	timer->base = of_iomap(node, 0); -	if (!timer->base) { -		pr_err("%s: of_iomap failed\n", node->full_name); -		ret = -ENXIO; -		goto out_free; -	} - -	irq = irq_of_parse_and_map(node, 0); -	if (irq <= 0) { -		pr_err("%s: irq_of_parse_and_map failed\n", node->full_name); -		ret = -EINVAL; -		goto out_unmap; -	} - -	clk = of_clk_get(node, 0); -	if (IS_ERR(clk))  { -		pr_err("%s: of_clk_get failed\n", node->full_name); -		ret = PTR_ERR(clk); -		goto out_unmap; -	} - -	pclk = clk_get_rate(clk); - -	if (of_device_is_compatible(node, "moxa,moxart-timer")) { -		timer->t1_enable_val = MOXART_TIMER1_ENABLE; -		timer->t1_disable_val = MOXART_TIMER1_DISABLE; -	} else if (of_device_is_compatible(node, "aspeed,ast2400-timer")) { -		timer->t1_enable_val = ASPEED_TIMER1_ENABLE; -		timer->t1_disable_val = ASPEED_TIMER1_DISABLE; -	} else { -		pr_err("%s: unknown platform\n", node->full_name); -		ret = -EINVAL; -		goto out_unmap; -	} - -	timer->count_per_tick = DIV_ROUND_CLOSEST(pclk, HZ); - -	timer->clkevt.name = node->name; -	timer->clkevt.rating = 200; -	timer->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | -					CLOCK_EVT_FEAT_ONESHOT; -	timer->clkevt.set_state_shutdown = moxart_shutdown; -	timer->clkevt.set_state_periodic = moxart_set_periodic; -	timer->clkevt.set_state_oneshot = moxart_set_oneshot; -	timer->clkevt.tick_resume = moxart_set_oneshot; -	timer->clkevt.set_next_event = moxart_clkevt_next_event; -	timer->clkevt.cpumask = cpumask_of(0); -	timer->clkevt.irq = irq; - -	ret = clocksource_mmio_init(timer->base + TIMER2_BASE + REG_COUNT, -				    "moxart_timer", pclk, 200, 32, -				    clocksource_mmio_readl_down); -	if (ret) { -		pr_err("%s: clocksource_mmio_init failed\n", node->full_name); -		goto out_unmap; -	} - -	ret = request_irq(irq, moxart_timer_interrupt, IRQF_TIMER, -			  node->name, &timer->clkevt); -	if (ret) { -		pr_err("%s: setup_irq failed\n", node->full_name); -		goto out_unmap; -	} - -	/* Clear match registers */ -	writel(0, timer->base + TIMER1_BASE + REG_MATCH1); -	writel(0, timer->base + TIMER1_BASE + REG_MATCH2); -	writel(0, timer->base + TIMER2_BASE + REG_MATCH1); -	writel(0, timer->base + TIMER2_BASE + REG_MATCH2); - -	/* -	 * Start timer 2 rolling as our main wall clock source, keep timer 1 -	 * disabled -	 */ -	writel(0, timer->base + TIMER_CR); -	writel(~0, timer->base + TIMER2_BASE + REG_LOAD); -	writel(timer->t1_disable_val, timer->base + TIMER_CR); - -	/* -	 * documentation is not publicly available: -	 * min_delta / max_delta obtained by trial-and-error, -	 * max_delta 0xfffffffe should be ok because count -	 * register size is u32 -	 */ -	clockevents_config_and_register(&timer->clkevt, pclk, 0x4, 0xfffffffe); - -	return 0; - -out_unmap: -	iounmap(timer->base); -out_free: -	kfree(timer); -	return ret; -} -CLOCKSOURCE_OF_DECLARE(moxart, "moxa,moxart-timer", moxart_timer_init); -CLOCKSOURCE_OF_DECLARE(aspeed, "aspeed,ast2400-timer", moxart_timer_init); diff --git a/drivers/clocksource/mps2-timer.c b/drivers/clocksource/mps2-timer.c index 3e4431ed9aa9..aa4d63af8706 100644 --- a/drivers/clocksource/mps2-timer.c +++ b/drivers/clocksource/mps2-timer.c @@ -274,4 +274,4 @@ static int __init mps2_timer_init(struct device_node *np)  	return 0;  } -CLOCKSOURCE_OF_DECLARE(mps2_timer, "arm,mps2-timer", mps2_timer_init); +TIMER_OF_DECLARE(mps2_timer, "arm,mps2-timer", mps2_timer_init); diff --git a/drivers/clocksource/mtk_timer.c b/drivers/clocksource/mtk_timer.c index 90659493c59c..f9b724fd9950 100644 --- a/drivers/clocksource/mtk_timer.c +++ b/drivers/clocksource/mtk_timer.c @@ -265,4 +265,4 @@ err_kzalloc:  	return -EINVAL;  } -CLOCKSOURCE_OF_DECLARE(mtk_mt6577, "mediatek,mt6577-timer", mtk_timer_init); +TIMER_OF_DECLARE(mtk_mt6577, "mediatek,mt6577-timer", mtk_timer_init); diff --git a/drivers/clocksource/mxs_timer.c b/drivers/clocksource/mxs_timer.c index 99b77aff0839..a03434e9fe8f 100644 --- a/drivers/clocksource/mxs_timer.c +++ b/drivers/clocksource/mxs_timer.c @@ -293,4 +293,4 @@ static int __init mxs_timer_init(struct device_node *np)  	return setup_irq(irq, &mxs_timer_irq);  } -CLOCKSOURCE_OF_DECLARE(mxs, "fsl,timrot", mxs_timer_init); +TIMER_OF_DECLARE(mxs, "fsl,timrot", mxs_timer_init); diff --git a/drivers/clocksource/nomadik-mtu.c b/drivers/clocksource/nomadik-mtu.c index 7d44de304f37..8e4ddb9420c6 100644 --- a/drivers/clocksource/nomadik-mtu.c +++ b/drivers/clocksource/nomadik-mtu.c @@ -284,5 +284,5 @@ static int __init nmdk_timer_of_init(struct device_node *node)  	return nmdk_timer_init(base, irq, pclk, clk);  } -CLOCKSOURCE_OF_DECLARE(nomadik_mtu, "st,nomadik-mtu", +TIMER_OF_DECLARE(nomadik_mtu, "st,nomadik-mtu",  		       nmdk_timer_of_init); diff --git a/drivers/clocksource/pxa_timer.c b/drivers/clocksource/pxa_timer.c index a10fa667325f..08cd6eaf3795 100644 --- a/drivers/clocksource/pxa_timer.c +++ b/drivers/clocksource/pxa_timer.c @@ -216,7 +216,7 @@ static int __init pxa_timer_dt_init(struct device_node *np)  	return pxa_timer_common_init(irq, clk_get_rate(clk));  } -CLOCKSOURCE_OF_DECLARE(pxa_timer, "marvell,pxa-timer", pxa_timer_dt_init); +TIMER_OF_DECLARE(pxa_timer, "marvell,pxa-timer", pxa_timer_dt_init);  /*   * Legacy timer init for non device-tree boards. diff --git a/drivers/clocksource/qcom-timer.c b/drivers/clocksource/qcom-timer.c index ee358cdf4a07..89816f89ff3f 100644 --- a/drivers/clocksource/qcom-timer.c +++ b/drivers/clocksource/qcom-timer.c @@ -254,5 +254,5 @@ static int __init msm_dt_timer_init(struct device_node *np)  	return msm_timer_init(freq, 32, irq, !!percpu_offset);  } -CLOCKSOURCE_OF_DECLARE(kpss_timer, "qcom,kpss-timer", msm_dt_timer_init); -CLOCKSOURCE_OF_DECLARE(scss_timer, "qcom,scss-timer", msm_dt_timer_init); +TIMER_OF_DECLARE(kpss_timer, "qcom,kpss-timer", msm_dt_timer_init); +TIMER_OF_DECLARE(scss_timer, "qcom,scss-timer", msm_dt_timer_init); diff --git a/drivers/clocksource/renesas-ostm.c b/drivers/clocksource/renesas-ostm.c index c76f57668fb2..6cffd7c6001a 100644 --- a/drivers/clocksource/renesas-ostm.c +++ b/drivers/clocksource/renesas-ostm.c @@ -262,4 +262,4 @@ err:  	return 0;  } -CLOCKSOURCE_OF_DECLARE(ostm, "renesas,ostm", ostm_init); +TIMER_OF_DECLARE(ostm, "renesas,ostm", ostm_init); diff --git a/drivers/clocksource/rockchip_timer.c b/drivers/clocksource/rockchip_timer.c index 49c02be50eca..c27f4c850d83 100644 --- a/drivers/clocksource/rockchip_timer.c +++ b/drivers/clocksource/rockchip_timer.c @@ -303,5 +303,5 @@ static int __init rk_timer_init(struct device_node *np)  	return -EINVAL;  } -CLOCKSOURCE_OF_DECLARE(rk3288_timer, "rockchip,rk3288-timer", rk_timer_init); -CLOCKSOURCE_OF_DECLARE(rk3399_timer, "rockchip,rk3399-timer", rk_timer_init); +TIMER_OF_DECLARE(rk3288_timer, "rockchip,rk3288-timer", rk_timer_init); +TIMER_OF_DECLARE(rk3399_timer, "rockchip,rk3399-timer", rk_timer_init); diff --git a/drivers/clocksource/samsung_pwm_timer.c b/drivers/clocksource/samsung_pwm_timer.c index a68e6538c809..6d5d126357c2 100644 --- a/drivers/clocksource/samsung_pwm_timer.c +++ b/drivers/clocksource/samsung_pwm_timer.c @@ -418,7 +418,7 @@ void __init samsung_pwm_clocksource_init(void __iomem *base,  	_samsung_pwm_clocksource_init();  } -#ifdef CONFIG_CLKSRC_OF +#ifdef CONFIG_TIMER_OF  static int __init samsung_pwm_alloc(struct device_node *np,  				    const struct samsung_pwm_variant *variant)  { @@ -466,7 +466,7 @@ static int __init s3c2410_pwm_clocksource_init(struct device_node *np)  {  	return samsung_pwm_alloc(np, &s3c24xx_variant);  } -CLOCKSOURCE_OF_DECLARE(s3c2410_pwm, "samsung,s3c2410-pwm", s3c2410_pwm_clocksource_init); +TIMER_OF_DECLARE(s3c2410_pwm, "samsung,s3c2410-pwm", s3c2410_pwm_clocksource_init);  static const struct samsung_pwm_variant s3c64xx_variant = {  	.bits		= 32, @@ -479,7 +479,7 @@ static int __init s3c64xx_pwm_clocksource_init(struct device_node *np)  {  	return samsung_pwm_alloc(np, &s3c64xx_variant);  } -CLOCKSOURCE_OF_DECLARE(s3c6400_pwm, "samsung,s3c6400-pwm", s3c64xx_pwm_clocksource_init); +TIMER_OF_DECLARE(s3c6400_pwm, "samsung,s3c6400-pwm", s3c64xx_pwm_clocksource_init);  static const struct samsung_pwm_variant s5p64x0_variant = {  	.bits		= 32, @@ -492,7 +492,7 @@ static int __init s5p64x0_pwm_clocksource_init(struct device_node *np)  {  	return samsung_pwm_alloc(np, &s5p64x0_variant);  } -CLOCKSOURCE_OF_DECLARE(s5p6440_pwm, "samsung,s5p6440-pwm", s5p64x0_pwm_clocksource_init); +TIMER_OF_DECLARE(s5p6440_pwm, "samsung,s5p6440-pwm", s5p64x0_pwm_clocksource_init);  static const struct samsung_pwm_variant s5p_variant = {  	.bits		= 32, @@ -505,5 +505,5 @@ static int __init s5p_pwm_clocksource_init(struct device_node *np)  {  	return samsung_pwm_alloc(np, &s5p_variant);  } -CLOCKSOURCE_OF_DECLARE(s5pc100_pwm, "samsung,s5pc100-pwm", s5p_pwm_clocksource_init); +TIMER_OF_DECLARE(s5pc100_pwm, "samsung,s5pc100-pwm", s5p_pwm_clocksource_init);  #endif diff --git a/drivers/clocksource/sun4i_timer.c b/drivers/clocksource/sun4i_timer.c index 4452d5c8f304..6e0180aaf784 100644 --- a/drivers/clocksource/sun4i_timer.c +++ b/drivers/clocksource/sun4i_timer.c @@ -24,6 +24,8 @@  #include <linux/of_address.h>  #include <linux/of_irq.h> +#include "timer-of.h" +  #define TIMER_IRQ_EN_REG	0x00  #define TIMER_IRQ_EN(val)		BIT(val)  #define TIMER_IRQ_ST_REG	0x04 @@ -39,38 +41,37 @@  #define TIMER_SYNC_TICKS	3 -static void __iomem *timer_base; -static u32 ticks_per_jiffy; -  /*   * When we disable a timer, we need to wait at least for 2 cycles of   * the timer source clock. We will use for that the clocksource timer   * that is already setup and runs at the same frequency than the other   * timers, and we never will be disabled.   */ -static void sun4i_clkevt_sync(void) +static void sun4i_clkevt_sync(void __iomem *base)  { -	u32 old = readl(timer_base + TIMER_CNTVAL_REG(1)); +	u32 old = readl(base + TIMER_CNTVAL_REG(1)); -	while ((old - readl(timer_base + TIMER_CNTVAL_REG(1))) < TIMER_SYNC_TICKS) +	while ((old - readl(base + TIMER_CNTVAL_REG(1))) < TIMER_SYNC_TICKS)  		cpu_relax();  } -static void sun4i_clkevt_time_stop(u8 timer) +static void sun4i_clkevt_time_stop(void __iomem *base, u8 timer)  { -	u32 val = readl(timer_base + TIMER_CTL_REG(timer)); -	writel(val & ~TIMER_CTL_ENABLE, timer_base + TIMER_CTL_REG(timer)); -	sun4i_clkevt_sync(); +	u32 val = readl(base + TIMER_CTL_REG(timer)); +	writel(val & ~TIMER_CTL_ENABLE, base + TIMER_CTL_REG(timer)); +	sun4i_clkevt_sync(base);  } -static void sun4i_clkevt_time_setup(u8 timer, unsigned long delay) +static void sun4i_clkevt_time_setup(void __iomem *base, u8 timer, +				    unsigned long delay)  { -	writel(delay, timer_base + TIMER_INTVAL_REG(timer)); +	writel(delay, base + TIMER_INTVAL_REG(timer));  } -static void sun4i_clkevt_time_start(u8 timer, bool periodic) +static void sun4i_clkevt_time_start(void __iomem *base, u8 timer, +				    bool periodic)  { -	u32 val = readl(timer_base + TIMER_CTL_REG(timer)); +	u32 val = readl(base + TIMER_CTL_REG(timer));  	if (periodic)  		val &= ~TIMER_CTL_ONESHOT; @@ -78,115 +79,106 @@ static void sun4i_clkevt_time_start(u8 timer, bool periodic)  		val |= TIMER_CTL_ONESHOT;  	writel(val | TIMER_CTL_ENABLE | TIMER_CTL_RELOAD, -	       timer_base + TIMER_CTL_REG(timer)); +	       base + TIMER_CTL_REG(timer));  }  static int sun4i_clkevt_shutdown(struct clock_event_device *evt)  { -	sun4i_clkevt_time_stop(0); +	struct timer_of *to = to_timer_of(evt); + +	sun4i_clkevt_time_stop(timer_of_base(to), 0); +  	return 0;  }  static int sun4i_clkevt_set_oneshot(struct clock_event_device *evt)  { -	sun4i_clkevt_time_stop(0); -	sun4i_clkevt_time_start(0, false); +	struct timer_of *to = to_timer_of(evt); + +	sun4i_clkevt_time_stop(timer_of_base(to), 0); +	sun4i_clkevt_time_start(timer_of_base(to), 0, false); +  	return 0;  }  static int sun4i_clkevt_set_periodic(struct clock_event_device *evt)  { -	sun4i_clkevt_time_stop(0); -	sun4i_clkevt_time_setup(0, ticks_per_jiffy); -	sun4i_clkevt_time_start(0, true); +	struct timer_of *to = to_timer_of(evt); + +	sun4i_clkevt_time_stop(timer_of_base(to), 0); +	sun4i_clkevt_time_setup(timer_of_base(to), 0, timer_of_period(to)); +	sun4i_clkevt_time_start(timer_of_base(to), 0, true); +  	return 0;  }  static int sun4i_clkevt_next_event(unsigned long evt, -				   struct clock_event_device *unused) +				   struct clock_event_device *clkevt)  { -	sun4i_clkevt_time_stop(0); -	sun4i_clkevt_time_setup(0, evt - TIMER_SYNC_TICKS); -	sun4i_clkevt_time_start(0, false); +	struct timer_of *to = to_timer_of(clkevt); + +	sun4i_clkevt_time_stop(timer_of_base(to), 0); +	sun4i_clkevt_time_setup(timer_of_base(to), 0, evt - TIMER_SYNC_TICKS); +	sun4i_clkevt_time_start(timer_of_base(to), 0, false);  	return 0;  } -static struct clock_event_device sun4i_clockevent = { -	.name = "sun4i_tick", -	.rating = 350, -	.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, -	.set_state_shutdown = sun4i_clkevt_shutdown, -	.set_state_periodic = sun4i_clkevt_set_periodic, -	.set_state_oneshot = sun4i_clkevt_set_oneshot, -	.tick_resume = sun4i_clkevt_shutdown, -	.set_next_event = sun4i_clkevt_next_event, -}; - -static void sun4i_timer_clear_interrupt(void) +static void sun4i_timer_clear_interrupt(void __iomem *base)  { -	writel(TIMER_IRQ_EN(0), timer_base + TIMER_IRQ_ST_REG); +	writel(TIMER_IRQ_EN(0), base + TIMER_IRQ_ST_REG);  }  static irqreturn_t sun4i_timer_interrupt(int irq, void *dev_id)  {  	struct clock_event_device *evt = (struct clock_event_device *)dev_id; +	struct timer_of *to = to_timer_of(evt); -	sun4i_timer_clear_interrupt(); +	sun4i_timer_clear_interrupt(timer_of_base(to));  	evt->event_handler(evt);  	return IRQ_HANDLED;  } -static struct irqaction sun4i_timer_irq = { -	.name = "sun4i_timer0", -	.flags = IRQF_TIMER | IRQF_IRQPOLL, -	.handler = sun4i_timer_interrupt, -	.dev_id = &sun4i_clockevent, +static struct timer_of to = { +	.flags = TIMER_OF_IRQ | TIMER_OF_CLOCK | TIMER_OF_BASE, + +	.clkevt = { +		.name = "sun4i_tick", +		.rating = 350, +		.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, +		.set_state_shutdown = sun4i_clkevt_shutdown, +		.set_state_periodic = sun4i_clkevt_set_periodic, +		.set_state_oneshot = sun4i_clkevt_set_oneshot, +		.tick_resume = sun4i_clkevt_shutdown, +		.set_next_event = sun4i_clkevt_next_event, +		.cpumask = cpu_possible_mask, +	}, + +	.of_irq = { +		.handler = sun4i_timer_interrupt, +		.flags = IRQF_TIMER | IRQF_IRQPOLL, +	},  };  static u64 notrace sun4i_timer_sched_read(void)  { -	return ~readl(timer_base + TIMER_CNTVAL_REG(1)); +	return ~readl(timer_of_base(&to) + TIMER_CNTVAL_REG(1));  }  static int __init sun4i_timer_init(struct device_node *node)  { -	unsigned long rate = 0; -	struct clk *clk; -	int ret, irq; +	int ret;  	u32 val; -	timer_base = of_iomap(node, 0); -	if (!timer_base) { -		pr_crit("Can't map registers\n"); -		return -ENXIO; -	} - -	irq = irq_of_parse_and_map(node, 0); -	if (irq <= 0) { -		pr_crit("Can't parse IRQ\n"); -		return -EINVAL; -	} - -	clk = of_clk_get(node, 0); -	if (IS_ERR(clk)) { -		pr_crit("Can't get timer clock\n"); -		return PTR_ERR(clk); -	} - -	ret = clk_prepare_enable(clk); -	if (ret) { -		pr_err("Failed to prepare clock\n"); +	ret = timer_of_init(node, &to); +	if (ret)  		return ret; -	} - -	rate = clk_get_rate(clk); -	writel(~0, timer_base + TIMER_INTVAL_REG(1)); +	writel(~0, timer_of_base(&to) + TIMER_INTVAL_REG(1));  	writel(TIMER_CTL_ENABLE | TIMER_CTL_RELOAD |  	       TIMER_CTL_CLK_SRC(TIMER_CTL_CLK_SRC_OSC24M), -	       timer_base + TIMER_CTL_REG(1)); +	       timer_of_base(&to) + TIMER_CTL_REG(1));  	/*  	 * sched_clock_register does not have priorities, and on sun6i and @@ -195,43 +187,34 @@ static int __init sun4i_timer_init(struct device_node *node)  	if (of_machine_is_compatible("allwinner,sun4i-a10") ||  	    of_machine_is_compatible("allwinner,sun5i-a13") ||  	    of_machine_is_compatible("allwinner,sun5i-a10s")) -		sched_clock_register(sun4i_timer_sched_read, 32, rate); +		sched_clock_register(sun4i_timer_sched_read, 32, +				     timer_of_rate(&to)); -	ret = clocksource_mmio_init(timer_base + TIMER_CNTVAL_REG(1), node->name, -				    rate, 350, 32, clocksource_mmio_readl_down); +	ret = clocksource_mmio_init(timer_of_base(&to) + TIMER_CNTVAL_REG(1), +				    node->name, timer_of_rate(&to), 350, 32, +				    clocksource_mmio_readl_down);  	if (ret) {  		pr_err("Failed to register clocksource\n");  		return ret;  	} -	ticks_per_jiffy = DIV_ROUND_UP(rate, HZ); -  	writel(TIMER_CTL_CLK_SRC(TIMER_CTL_CLK_SRC_OSC24M), -	       timer_base + TIMER_CTL_REG(0)); +	       timer_of_base(&to) + TIMER_CTL_REG(0));  	/* Make sure timer is stopped before playing with interrupts */ -	sun4i_clkevt_time_stop(0); +	sun4i_clkevt_time_stop(timer_of_base(&to), 0);  	/* clear timer0 interrupt */ -	sun4i_timer_clear_interrupt(); - -	sun4i_clockevent.cpumask = cpu_possible_mask; -	sun4i_clockevent.irq = irq; +	sun4i_timer_clear_interrupt(timer_of_base(&to)); -	clockevents_config_and_register(&sun4i_clockevent, rate, +	clockevents_config_and_register(&to.clkevt, timer_of_rate(&to),  					TIMER_SYNC_TICKS, 0xffffffff); -	ret = setup_irq(irq, &sun4i_timer_irq); -	if (ret) { -		pr_err("failed to setup irq %d\n", irq); -		return ret; -	} -  	/* Enable timer0 interrupt */ -	val = readl(timer_base + TIMER_IRQ_EN_REG); -	writel(val | TIMER_IRQ_EN(0), timer_base + TIMER_IRQ_EN_REG); +	val = readl(timer_of_base(&to) + TIMER_IRQ_EN_REG); +	writel(val | TIMER_IRQ_EN(0), timer_of_base(&to) + TIMER_IRQ_EN_REG);  	return ret;  } -CLOCKSOURCE_OF_DECLARE(sun4i, "allwinner,sun4i-a10-timer", +TIMER_OF_DECLARE(sun4i, "allwinner,sun4i-a10-timer",  		       sun4i_timer_init); diff --git a/drivers/clocksource/tango_xtal.c b/drivers/clocksource/tango_xtal.c index 12fcef8cf2d3..c4e1c2e6046f 100644 --- a/drivers/clocksource/tango_xtal.c +++ b/drivers/clocksource/tango_xtal.c @@ -53,4 +53,4 @@ static int __init tango_clocksource_init(struct device_node *np)  	return 0;  } -CLOCKSOURCE_OF_DECLARE(tango, "sigma,tick-counter", tango_clocksource_init); +TIMER_OF_DECLARE(tango, "sigma,tick-counter", tango_clocksource_init); diff --git a/drivers/clocksource/tcb_clksrc.c b/drivers/clocksource/tcb_clksrc.c index d4ca9962a759..59e8aee0ec16 100644 --- a/drivers/clocksource/tcb_clksrc.c +++ b/drivers/clocksource/tcb_clksrc.c @@ -9,6 +9,7 @@  #include <linux/ioport.h>  #include <linux/io.h>  #include <linux/platform_device.h> +#include <linux/syscore_ops.h>  #include <linux/atmel_tc.h> @@ -40,6 +41,14 @@   */  static void __iomem *tcaddr; +static struct +{ +	u32 cmr; +	u32 imr; +	u32 rc; +	bool clken; +} tcb_cache[3]; +static u32 bmr_cache;  static u64 tc_get_cycles(struct clocksource *cs)  { @@ -48,9 +57,9 @@ static u64 tc_get_cycles(struct clocksource *cs)  	raw_local_irq_save(flags);  	do { -		upper = __raw_readl(tcaddr + ATMEL_TC_REG(1, CV)); -		lower = __raw_readl(tcaddr + ATMEL_TC_REG(0, CV)); -	} while (upper != __raw_readl(tcaddr + ATMEL_TC_REG(1, CV))); +		upper = readl_relaxed(tcaddr + ATMEL_TC_REG(1, CV)); +		lower = readl_relaxed(tcaddr + ATMEL_TC_REG(0, CV)); +	} while (upper != readl_relaxed(tcaddr + ATMEL_TC_REG(1, CV)));  	raw_local_irq_restore(flags);  	return (upper << 16) | lower; @@ -58,7 +67,47 @@ static u64 tc_get_cycles(struct clocksource *cs)  static u64 tc_get_cycles32(struct clocksource *cs)  { -	return __raw_readl(tcaddr + ATMEL_TC_REG(0, CV)); +	return readl_relaxed(tcaddr + ATMEL_TC_REG(0, CV)); +} + +void tc_clksrc_suspend(struct clocksource *cs) +{ +	int i; + +	for (i = 0; i < ARRAY_SIZE(tcb_cache); i++) { +		tcb_cache[i].cmr = readl(tcaddr + ATMEL_TC_REG(i, CMR)); +		tcb_cache[i].imr = readl(tcaddr + ATMEL_TC_REG(i, IMR)); +		tcb_cache[i].rc = readl(tcaddr + ATMEL_TC_REG(i, RC)); +		tcb_cache[i].clken = !!(readl(tcaddr + ATMEL_TC_REG(i, SR)) & +					ATMEL_TC_CLKSTA); +	} + +	bmr_cache = readl(tcaddr + ATMEL_TC_BMR); +} + +void tc_clksrc_resume(struct clocksource *cs) +{ +	int i; + +	for (i = 0; i < ARRAY_SIZE(tcb_cache); i++) { +		/* Restore registers for the channel, RA and RB are not used  */ +		writel(tcb_cache[i].cmr, tcaddr + ATMEL_TC_REG(i, CMR)); +		writel(tcb_cache[i].rc, tcaddr + ATMEL_TC_REG(i, RC)); +		writel(0, tcaddr + ATMEL_TC_REG(i, RA)); +		writel(0, tcaddr + ATMEL_TC_REG(i, RB)); +		/* Disable all the interrupts */ +		writel(0xff, tcaddr + ATMEL_TC_REG(i, IDR)); +		/* Reenable interrupts that were enabled before suspending */ +		writel(tcb_cache[i].imr, tcaddr + ATMEL_TC_REG(i, IER)); +		/* Start the clock if it was used */ +		if (tcb_cache[i].clken) +			writel(ATMEL_TC_CLKEN, tcaddr + ATMEL_TC_REG(i, CCR)); +	} + +	/* Dual channel, chain channels */ +	writel(bmr_cache, tcaddr + ATMEL_TC_BMR); +	/* Finally, trigger all the channels*/ +	writel(ATMEL_TC_SYNC, tcaddr + ATMEL_TC_BCR);  }  static struct clocksource clksrc = { @@ -67,6 +116,8 @@ static struct clocksource clksrc = {  	.read           = tc_get_cycles,  	.mask           = CLOCKSOURCE_MASK(32),  	.flags		= CLOCK_SOURCE_IS_CONTINUOUS, +	.suspend	= tc_clksrc_suspend, +	.resume		= tc_clksrc_resume,  };  #ifdef CONFIG_GENERIC_CLOCKEVENTS @@ -96,8 +147,8 @@ static int tc_shutdown(struct clock_event_device *d)  	struct tc_clkevt_device *tcd = to_tc_clkevt(d);  	void __iomem		*regs = tcd->regs; -	__raw_writel(0xff, regs + ATMEL_TC_REG(2, IDR)); -	__raw_writel(ATMEL_TC_CLKDIS, regs + ATMEL_TC_REG(2, CCR)); +	writel(0xff, regs + ATMEL_TC_REG(2, IDR)); +	writel(ATMEL_TC_CLKDIS, regs + ATMEL_TC_REG(2, CCR));  	if (!clockevent_state_detached(d))  		clk_disable(tcd->clk); @@ -115,9 +166,9 @@ static int tc_set_oneshot(struct clock_event_device *d)  	clk_enable(tcd->clk);  	/* slow clock, count up to RC, then irq and stop */ -	__raw_writel(timer_clock | ATMEL_TC_CPCSTOP | ATMEL_TC_WAVE | +	writel(timer_clock | ATMEL_TC_CPCSTOP | ATMEL_TC_WAVE |  		     ATMEL_TC_WAVESEL_UP_AUTO, regs + ATMEL_TC_REG(2, CMR)); -	__raw_writel(ATMEL_TC_CPCS, regs + ATMEL_TC_REG(2, IER)); +	writel(ATMEL_TC_CPCS, regs + ATMEL_TC_REG(2, IER));  	/* set_next_event() configures and starts the timer */  	return 0; @@ -137,25 +188,25 @@ static int tc_set_periodic(struct clock_event_device *d)  	clk_enable(tcd->clk);  	/* slow clock, count up to RC, then irq and restart */ -	__raw_writel(timer_clock | ATMEL_TC_WAVE | ATMEL_TC_WAVESEL_UP_AUTO, +	writel(timer_clock | ATMEL_TC_WAVE | ATMEL_TC_WAVESEL_UP_AUTO,  		     regs + ATMEL_TC_REG(2, CMR)); -	__raw_writel((32768 + HZ / 2) / HZ, tcaddr + ATMEL_TC_REG(2, RC)); +	writel((32768 + HZ / 2) / HZ, tcaddr + ATMEL_TC_REG(2, RC));  	/* Enable clock and interrupts on RC compare */ -	__raw_writel(ATMEL_TC_CPCS, regs + ATMEL_TC_REG(2, IER)); +	writel(ATMEL_TC_CPCS, regs + ATMEL_TC_REG(2, IER));  	/* go go gadget! */ -	__raw_writel(ATMEL_TC_CLKEN | ATMEL_TC_SWTRG, regs + +	writel(ATMEL_TC_CLKEN | ATMEL_TC_SWTRG, regs +  		     ATMEL_TC_REG(2, CCR));  	return 0;  }  static int tc_next_event(unsigned long delta, struct clock_event_device *d)  { -	__raw_writel(delta, tcaddr + ATMEL_TC_REG(2, RC)); +	writel_relaxed(delta, tcaddr + ATMEL_TC_REG(2, RC));  	/* go go gadget! */ -	__raw_writel(ATMEL_TC_CLKEN | ATMEL_TC_SWTRG, +	writel_relaxed(ATMEL_TC_CLKEN | ATMEL_TC_SWTRG,  			tcaddr + ATMEL_TC_REG(2, CCR));  	return 0;  } @@ -179,7 +230,7 @@ static irqreturn_t ch2_irq(int irq, void *handle)  	struct tc_clkevt_device	*dev = handle;  	unsigned int		sr; -	sr = __raw_readl(dev->regs + ATMEL_TC_REG(2, SR)); +	sr = readl_relaxed(dev->regs + ATMEL_TC_REG(2, SR));  	if (sr & ATMEL_TC_CPCS) {  		dev->clkevt.event_handler(&dev->clkevt);  		return IRQ_HANDLED; @@ -239,43 +290,43 @@ static int __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx)  static void __init tcb_setup_dual_chan(struct atmel_tc *tc, int mck_divisor_idx)  {  	/* channel 0:  waveform mode, input mclk/8, clock TIOA0 on overflow */ -	__raw_writel(mck_divisor_idx			/* likely divide-by-8 */ +	writel(mck_divisor_idx			/* likely divide-by-8 */  			| ATMEL_TC_WAVE  			| ATMEL_TC_WAVESEL_UP		/* free-run */  			| ATMEL_TC_ACPA_SET		/* TIOA0 rises at 0 */  			| ATMEL_TC_ACPC_CLEAR,		/* (duty cycle 50%) */  			tcaddr + ATMEL_TC_REG(0, CMR)); -	__raw_writel(0x0000, tcaddr + ATMEL_TC_REG(0, RA)); -	__raw_writel(0x8000, tcaddr + ATMEL_TC_REG(0, RC)); -	__raw_writel(0xff, tcaddr + ATMEL_TC_REG(0, IDR));	/* no irqs */ -	__raw_writel(ATMEL_TC_CLKEN, tcaddr + ATMEL_TC_REG(0, CCR)); +	writel(0x0000, tcaddr + ATMEL_TC_REG(0, RA)); +	writel(0x8000, tcaddr + ATMEL_TC_REG(0, RC)); +	writel(0xff, tcaddr + ATMEL_TC_REG(0, IDR));	/* no irqs */ +	writel(ATMEL_TC_CLKEN, tcaddr + ATMEL_TC_REG(0, CCR));  	/* channel 1:  waveform mode, input TIOA0 */ -	__raw_writel(ATMEL_TC_XC1			/* input: TIOA0 */ +	writel(ATMEL_TC_XC1			/* input: TIOA0 */  			| ATMEL_TC_WAVE  			| ATMEL_TC_WAVESEL_UP,		/* free-run */  			tcaddr + ATMEL_TC_REG(1, CMR)); -	__raw_writel(0xff, tcaddr + ATMEL_TC_REG(1, IDR));	/* no irqs */ -	__raw_writel(ATMEL_TC_CLKEN, tcaddr + ATMEL_TC_REG(1, CCR)); +	writel(0xff, tcaddr + ATMEL_TC_REG(1, IDR));	/* no irqs */ +	writel(ATMEL_TC_CLKEN, tcaddr + ATMEL_TC_REG(1, CCR));  	/* chain channel 0 to channel 1*/ -	__raw_writel(ATMEL_TC_TC1XC1S_TIOA0, tcaddr + ATMEL_TC_BMR); +	writel(ATMEL_TC_TC1XC1S_TIOA0, tcaddr + ATMEL_TC_BMR);  	/* then reset all the timers */ -	__raw_writel(ATMEL_TC_SYNC, tcaddr + ATMEL_TC_BCR); +	writel(ATMEL_TC_SYNC, tcaddr + ATMEL_TC_BCR);  }  static void __init tcb_setup_single_chan(struct atmel_tc *tc, int mck_divisor_idx)  {  	/* channel 0:  waveform mode, input mclk/8 */ -	__raw_writel(mck_divisor_idx			/* likely divide-by-8 */ +	writel(mck_divisor_idx			/* likely divide-by-8 */  			| ATMEL_TC_WAVE  			| ATMEL_TC_WAVESEL_UP,		/* free-run */  			tcaddr + ATMEL_TC_REG(0, CMR)); -	__raw_writel(0xff, tcaddr + ATMEL_TC_REG(0, IDR));	/* no irqs */ -	__raw_writel(ATMEL_TC_CLKEN, tcaddr + ATMEL_TC_REG(0, CCR)); +	writel(0xff, tcaddr + ATMEL_TC_REG(0, IDR));	/* no irqs */ +	writel(ATMEL_TC_CLKEN, tcaddr + ATMEL_TC_REG(0, CCR));  	/* then reset all the timers */ -	__raw_writel(ATMEL_TC_SYNC, tcaddr + ATMEL_TC_BCR); +	writel(ATMEL_TC_SYNC, tcaddr + ATMEL_TC_BCR);  }  static int __init tcb_clksrc_init(void) diff --git a/drivers/clocksource/tegra20_timer.c b/drivers/clocksource/tegra20_timer.c index b9990b9c98c5..c337a8100a7b 100644 --- a/drivers/clocksource/tegra20_timer.c +++ b/drivers/clocksource/tegra20_timer.c @@ -237,7 +237,7 @@ static int __init tegra20_init_timer(struct device_node *np)  	return 0;  } -CLOCKSOURCE_OF_DECLARE(tegra20_timer, "nvidia,tegra20-timer", tegra20_init_timer); +TIMER_OF_DECLARE(tegra20_timer, "nvidia,tegra20-timer", tegra20_init_timer);  static int __init tegra20_init_rtc(struct device_node *np)  { @@ -261,4 +261,4 @@ static int __init tegra20_init_rtc(struct device_node *np)  	return register_persistent_clock(NULL, tegra_read_persistent_clock64);  } -CLOCKSOURCE_OF_DECLARE(tegra20_rtc, "nvidia,tegra20-rtc", tegra20_init_rtc); +TIMER_OF_DECLARE(tegra20_rtc, "nvidia,tegra20-rtc", tegra20_init_rtc); diff --git a/drivers/clocksource/time-armada-370-xp.c b/drivers/clocksource/time-armada-370-xp.c index aea4380129ea..edf1a46269f1 100644 --- a/drivers/clocksource/time-armada-370-xp.c +++ b/drivers/clocksource/time-armada-370-xp.c @@ -351,7 +351,7 @@ static int __init armada_xp_timer_init(struct device_node *np)  	return armada_370_xp_timer_common_init(np);  } -CLOCKSOURCE_OF_DECLARE(armada_xp, "marvell,armada-xp-timer", +TIMER_OF_DECLARE(armada_xp, "marvell,armada-xp-timer",  		       armada_xp_timer_init);  static int __init armada_375_timer_init(struct device_node *np) @@ -389,7 +389,7 @@ static int __init armada_375_timer_init(struct device_node *np)  	return armada_370_xp_timer_common_init(np);  } -CLOCKSOURCE_OF_DECLARE(armada_375, "marvell,armada-375-timer", +TIMER_OF_DECLARE(armada_375, "marvell,armada-375-timer",  		       armada_375_timer_init);  static int __init armada_370_timer_init(struct device_node *np) @@ -412,5 +412,5 @@ static int __init armada_370_timer_init(struct device_node *np)  	return armada_370_xp_timer_common_init(np);  } -CLOCKSOURCE_OF_DECLARE(armada_370, "marvell,armada-370-timer", +TIMER_OF_DECLARE(armada_370, "marvell,armada-370-timer",  		       armada_370_timer_init); diff --git a/drivers/clocksource/time-efm32.c b/drivers/clocksource/time-efm32.c index ce0f97b4e5db..257e810ec1ad 100644 --- a/drivers/clocksource/time-efm32.c +++ b/drivers/clocksource/time-efm32.c @@ -283,5 +283,5 @@ static int __init efm32_timer_init(struct device_node *np)  	return ret;  } -CLOCKSOURCE_OF_DECLARE(efm32compat, "efm32,timer", efm32_timer_init); -CLOCKSOURCE_OF_DECLARE(efm32, "energymicro,efm32-timer", efm32_timer_init); +TIMER_OF_DECLARE(efm32compat, "efm32,timer", efm32_timer_init); +TIMER_OF_DECLARE(efm32, "energymicro,efm32-timer", efm32_timer_init); diff --git a/drivers/clocksource/time-lpc32xx.c b/drivers/clocksource/time-lpc32xx.c index 9649cfdb9213..d51a62a79ef7 100644 --- a/drivers/clocksource/time-lpc32xx.c +++ b/drivers/clocksource/time-lpc32xx.c @@ -311,4 +311,4 @@ static int __init lpc32xx_timer_init(struct device_node *np)  	return ret;  } -CLOCKSOURCE_OF_DECLARE(lpc32xx_timer, "nxp,lpc3220-timer", lpc32xx_timer_init); +TIMER_OF_DECLARE(lpc32xx_timer, "nxp,lpc3220-timer", lpc32xx_timer_init); diff --git a/drivers/clocksource/time-orion.c b/drivers/clocksource/time-orion.c index b9b97f630c4d..12202067fe4b 100644 --- a/drivers/clocksource/time-orion.c +++ b/drivers/clocksource/time-orion.c @@ -189,4 +189,4 @@ static int __init orion_timer_init(struct device_node *np)  	return 0;  } -CLOCKSOURCE_OF_DECLARE(orion_timer, "marvell,orion-timer", orion_timer_init); +TIMER_OF_DECLARE(orion_timer, "marvell,orion-timer", orion_timer_init); diff --git a/drivers/clocksource/time-pistachio.c b/drivers/clocksource/time-pistachio.c index 3710e4d9dcba..a2dd85d0c1d7 100644 --- a/drivers/clocksource/time-pistachio.c +++ b/drivers/clocksource/time-pistachio.c @@ -214,5 +214,5 @@ static int __init pistachio_clksrc_of_init(struct device_node *node)  	sched_clock_register(pistachio_read_sched_clock, 32, rate);  	return clocksource_register_hz(&pcs_gpt.cs, rate);  } -CLOCKSOURCE_OF_DECLARE(pistachio_gptimer, "img,pistachio-gptimer", +TIMER_OF_DECLARE(pistachio_gptimer, "img,pistachio-gptimer",  		       pistachio_clksrc_of_init); diff --git a/drivers/clocksource/timer-atlas7.c b/drivers/clocksource/timer-atlas7.c index 50300eec4a39..62c4bbc55a7e 100644 --- a/drivers/clocksource/timer-atlas7.c +++ b/drivers/clocksource/timer-atlas7.c @@ -283,4 +283,4 @@ static int __init sirfsoc_of_timer_init(struct device_node *np)  	return sirfsoc_atlas7_timer_init(np);  } -CLOCKSOURCE_OF_DECLARE(sirfsoc_atlas7_timer, "sirf,atlas7-tick", sirfsoc_of_timer_init); +TIMER_OF_DECLARE(sirfsoc_atlas7_timer, "sirf,atlas7-tick", sirfsoc_of_timer_init); diff --git a/drivers/clocksource/timer-atmel-pit.c b/drivers/clocksource/timer-atmel-pit.c index cc112351dc70..ec8a4376f74f 100644 --- a/drivers/clocksource/timer-atmel-pit.c +++ b/drivers/clocksource/timer-atmel-pit.c @@ -255,5 +255,5 @@ static int __init at91sam926x_pit_dt_init(struct device_node *node)  	return 0;  } -CLOCKSOURCE_OF_DECLARE(at91sam926x_pit, "atmel,at91sam9260-pit", +TIMER_OF_DECLARE(at91sam926x_pit, "atmel,at91sam9260-pit",  		       at91sam926x_pit_dt_init); diff --git a/drivers/clocksource/timer-atmel-st.c b/drivers/clocksource/timer-atmel-st.c index be4ac7604136..d2e660f475af 100644 --- a/drivers/clocksource/timer-atmel-st.c +++ b/drivers/clocksource/timer-atmel-st.c @@ -260,5 +260,5 @@ static int __init atmel_st_timer_init(struct device_node *node)  	/* register clocksource */  	return clocksource_register_hz(&clk32k, sclk_rate);  } -CLOCKSOURCE_OF_DECLARE(atmel_st_timer, "atmel,at91rm9200-st", +TIMER_OF_DECLARE(atmel_st_timer, "atmel,at91rm9200-st",  		       atmel_st_timer_init); diff --git a/drivers/clocksource/timer-digicolor.c b/drivers/clocksource/timer-digicolor.c index 94a161eb9cce..1e984a4d8ad0 100644 --- a/drivers/clocksource/timer-digicolor.c +++ b/drivers/clocksource/timer-digicolor.c @@ -203,5 +203,5 @@ static int __init digicolor_timer_init(struct device_node *node)  	return 0;  } -CLOCKSOURCE_OF_DECLARE(conexant_digicolor, "cnxt,cx92755-timer", +TIMER_OF_DECLARE(conexant_digicolor, "cnxt,cx92755-timer",  		       digicolor_timer_init); diff --git a/drivers/clocksource/timer-fttmr010.c b/drivers/clocksource/timer-fttmr010.c index b4a6f1e4bc54..66dd909960c6 100644 --- a/drivers/clocksource/timer-fttmr010.c +++ b/drivers/clocksource/timer-fttmr010.c @@ -11,12 +11,13 @@  #include <linux/of.h>  #include <linux/of_address.h>  #include <linux/of_irq.h> -#include <linux/mfd/syscon.h> -#include <linux/regmap.h>  #include <linux/clockchips.h>  #include <linux/clocksource.h>  #include <linux/sched_clock.h>  #include <linux/clk.h> +#include <linux/slab.h> +#include <linux/bitops.h> +#include <linux/delay.h>  /*   * Register definitions for the timers @@ -37,267 +38,368 @@  #define TIMER_INTR_STATE	(0x34)  #define TIMER_INTR_MASK		(0x38) -#define TIMER_1_CR_ENABLE	(1 << 0) -#define TIMER_1_CR_CLOCK	(1 << 1) -#define TIMER_1_CR_INT		(1 << 2) -#define TIMER_2_CR_ENABLE	(1 << 3) -#define TIMER_2_CR_CLOCK	(1 << 4) -#define TIMER_2_CR_INT		(1 << 5) -#define TIMER_3_CR_ENABLE	(1 << 6) -#define TIMER_3_CR_CLOCK	(1 << 7) -#define TIMER_3_CR_INT		(1 << 8) -#define TIMER_1_CR_UPDOWN	(1 << 9) -#define TIMER_2_CR_UPDOWN	(1 << 10) -#define TIMER_3_CR_UPDOWN	(1 << 11) -#define TIMER_DEFAULT_FLAGS	(TIMER_1_CR_UPDOWN | \ -				 TIMER_3_CR_ENABLE | \ -				 TIMER_3_CR_UPDOWN) - -#define TIMER_1_INT_MATCH1	(1 << 0) -#define TIMER_1_INT_MATCH2	(1 << 1) -#define TIMER_1_INT_OVERFLOW	(1 << 2) -#define TIMER_2_INT_MATCH1	(1 << 3) -#define TIMER_2_INT_MATCH2	(1 << 4) -#define TIMER_2_INT_OVERFLOW	(1 << 5) -#define TIMER_3_INT_MATCH1	(1 << 6) -#define TIMER_3_INT_MATCH2	(1 << 7) -#define TIMER_3_INT_OVERFLOW	(1 << 8) +#define TIMER_1_CR_ENABLE	BIT(0) +#define TIMER_1_CR_CLOCK	BIT(1) +#define TIMER_1_CR_INT		BIT(2) +#define TIMER_2_CR_ENABLE	BIT(3) +#define TIMER_2_CR_CLOCK	BIT(4) +#define TIMER_2_CR_INT		BIT(5) +#define TIMER_3_CR_ENABLE	BIT(6) +#define TIMER_3_CR_CLOCK	BIT(7) +#define TIMER_3_CR_INT		BIT(8) +#define TIMER_1_CR_UPDOWN	BIT(9) +#define TIMER_2_CR_UPDOWN	BIT(10) +#define TIMER_3_CR_UPDOWN	BIT(11) + +/* + * The Aspeed AST2400 moves bits around in the control register + * and lacks bits for setting the timer to count upwards. + */ +#define TIMER_1_CR_ASPEED_ENABLE	BIT(0) +#define TIMER_1_CR_ASPEED_CLOCK		BIT(1) +#define TIMER_1_CR_ASPEED_INT		BIT(2) +#define TIMER_2_CR_ASPEED_ENABLE	BIT(4) +#define TIMER_2_CR_ASPEED_CLOCK		BIT(5) +#define TIMER_2_CR_ASPEED_INT		BIT(6) +#define TIMER_3_CR_ASPEED_ENABLE	BIT(8) +#define TIMER_3_CR_ASPEED_CLOCK		BIT(9) +#define TIMER_3_CR_ASPEED_INT		BIT(10) + +#define TIMER_1_INT_MATCH1	BIT(0) +#define TIMER_1_INT_MATCH2	BIT(1) +#define TIMER_1_INT_OVERFLOW	BIT(2) +#define TIMER_2_INT_MATCH1	BIT(3) +#define TIMER_2_INT_MATCH2	BIT(4) +#define TIMER_2_INT_OVERFLOW	BIT(5) +#define TIMER_3_INT_MATCH1	BIT(6) +#define TIMER_3_INT_MATCH2	BIT(7) +#define TIMER_3_INT_OVERFLOW	BIT(8)  #define TIMER_INT_ALL_MASK	0x1ff -static unsigned int tick_rate; -static void __iomem *base; +struct fttmr010 { +	void __iomem *base; +	unsigned int tick_rate; +	bool count_down; +	u32 t1_enable_val; +	struct clock_event_device clkevt; +#ifdef CONFIG_ARM +	struct delay_timer delay_timer; +#endif +}; + +/* + * A local singleton used by sched_clock and delay timer reads, which are + * fast and stateless + */ +static struct fttmr010 *local_fttmr; + +static inline struct fttmr010 *to_fttmr010(struct clock_event_device *evt) +{ +	return container_of(evt, struct fttmr010, clkevt); +} + +static unsigned long fttmr010_read_current_timer_up(void) +{ +	return readl(local_fttmr->base + TIMER2_COUNT); +} + +static unsigned long fttmr010_read_current_timer_down(void) +{ +	return ~readl(local_fttmr->base + TIMER2_COUNT); +} + +static u64 notrace fttmr010_read_sched_clock_up(void) +{ +	return fttmr010_read_current_timer_up(); +} -static u64 notrace fttmr010_read_sched_clock(void) +static u64 notrace fttmr010_read_sched_clock_down(void)  { -	return readl(base + TIMER3_COUNT); +	return fttmr010_read_current_timer_down();  }  static int fttmr010_timer_set_next_event(unsigned long cycles,  				       struct clock_event_device *evt)  { +	struct fttmr010 *fttmr010 = to_fttmr010(evt);  	u32 cr; -	/* Setup the match register */ -	cr = readl(base + TIMER1_COUNT); -	writel(cr + cycles, base + TIMER1_MATCH1); -	if (readl(base + TIMER1_COUNT) - cr > cycles) -		return -ETIME; +	/* Stop */ +	cr = readl(fttmr010->base + TIMER_CR); +	cr &= ~fttmr010->t1_enable_val; +	writel(cr, fttmr010->base + TIMER_CR); + +	/* Setup the match register forward/backward in time */ +	cr = readl(fttmr010->base + TIMER1_COUNT); +	if (fttmr010->count_down) +		cr -= cycles; +	else +		cr += cycles; +	writel(cr, fttmr010->base + TIMER1_MATCH1); + +	/* Start */ +	cr = readl(fttmr010->base + TIMER_CR); +	cr |= fttmr010->t1_enable_val; +	writel(cr, fttmr010->base + TIMER_CR);  	return 0;  }  static int fttmr010_timer_shutdown(struct clock_event_device *evt)  { +	struct fttmr010 *fttmr010 = to_fttmr010(evt);  	u32 cr; -	/* -	 * Disable also for oneshot: the set_next() call will arm the timer -	 * instead. -	 */ -	/* Stop timer and interrupt. */ -	cr = readl(base + TIMER_CR); -	cr &= ~(TIMER_1_CR_ENABLE | TIMER_1_CR_INT); -	writel(cr, base + TIMER_CR); +	/* Stop */ +	cr = readl(fttmr010->base + TIMER_CR); +	cr &= ~fttmr010->t1_enable_val; +	writel(cr, fttmr010->base + TIMER_CR); + +	return 0; +} + +static int fttmr010_timer_set_oneshot(struct clock_event_device *evt) +{ +	struct fttmr010 *fttmr010 = to_fttmr010(evt); +	u32 cr; + +	/* Stop */ +	cr = readl(fttmr010->base + TIMER_CR); +	cr &= ~fttmr010->t1_enable_val; +	writel(cr, fttmr010->base + TIMER_CR); -	/* Setup counter start from 0 */ -	writel(0, base + TIMER1_COUNT); -	writel(0, base + TIMER1_LOAD); +	/* Setup counter start from 0 or ~0 */ +	writel(0, fttmr010->base + TIMER1_COUNT); +	if (fttmr010->count_down) +		writel(~0, fttmr010->base + TIMER1_LOAD); +	else +		writel(0, fttmr010->base + TIMER1_LOAD); -	/* enable interrupt */ -	cr = readl(base + TIMER_INTR_MASK); +	/* Enable interrupt */ +	cr = readl(fttmr010->base + TIMER_INTR_MASK);  	cr &= ~(TIMER_1_INT_OVERFLOW | TIMER_1_INT_MATCH2);  	cr |= TIMER_1_INT_MATCH1; -	writel(cr, base + TIMER_INTR_MASK); - -	/* start the timer */ -	cr = readl(base + TIMER_CR); -	cr |= TIMER_1_CR_ENABLE; -	writel(cr, base + TIMER_CR); +	writel(cr, fttmr010->base + TIMER_INTR_MASK);  	return 0;  }  static int fttmr010_timer_set_periodic(struct clock_event_device *evt)  { -	u32 period = DIV_ROUND_CLOSEST(tick_rate, HZ); +	struct fttmr010 *fttmr010 = to_fttmr010(evt); +	u32 period = DIV_ROUND_CLOSEST(fttmr010->tick_rate, HZ);  	u32 cr; -	/* Stop timer and interrupt */ -	cr = readl(base + TIMER_CR); -	cr &= ~(TIMER_1_CR_ENABLE | TIMER_1_CR_INT); -	writel(cr, base + TIMER_CR); - -	/* Setup timer to fire at 1/HT intervals. */ -	cr = 0xffffffff - (period - 1); -	writel(cr, base + TIMER1_COUNT); -	writel(cr, base + TIMER1_LOAD); - -	/* enable interrupt on overflow */ -	cr = readl(base + TIMER_INTR_MASK); -	cr &= ~(TIMER_1_INT_MATCH1 | TIMER_1_INT_MATCH2); -	cr |= TIMER_1_INT_OVERFLOW; -	writel(cr, base + TIMER_INTR_MASK); +	/* Stop */ +	cr = readl(fttmr010->base + TIMER_CR); +	cr &= ~fttmr010->t1_enable_val; +	writel(cr, fttmr010->base + TIMER_CR); + +	/* Setup timer to fire at 1/HZ intervals. */ +	if (fttmr010->count_down) { +		writel(period, fttmr010->base + TIMER1_LOAD); +		writel(0, fttmr010->base + TIMER1_MATCH1); +	} else { +		cr = 0xffffffff - (period - 1); +		writel(cr, fttmr010->base + TIMER1_COUNT); +		writel(cr, fttmr010->base + TIMER1_LOAD); + +		/* Enable interrupt on overflow */ +		cr = readl(fttmr010->base + TIMER_INTR_MASK); +		cr &= ~(TIMER_1_INT_MATCH1 | TIMER_1_INT_MATCH2); +		cr |= TIMER_1_INT_OVERFLOW; +		writel(cr, fttmr010->base + TIMER_INTR_MASK); +	}  	/* Start the timer */ -	cr = readl(base + TIMER_CR); -	cr |= TIMER_1_CR_ENABLE; -	cr |= TIMER_1_CR_INT; -	writel(cr, base + TIMER_CR); +	cr = readl(fttmr010->base + TIMER_CR); +	cr |= fttmr010->t1_enable_val; +	writel(cr, fttmr010->base + TIMER_CR);  	return 0;  } -/* Use TIMER1 as clock event */ -static struct clock_event_device fttmr010_clockevent = { -	.name			= "TIMER1", -	/* Reasonably fast and accurate clock event */ -	.rating			= 300, -	.shift                  = 32, -	.features		= CLOCK_EVT_FEAT_PERIODIC | -				  CLOCK_EVT_FEAT_ONESHOT, -	.set_next_event		= fttmr010_timer_set_next_event, -	.set_state_shutdown	= fttmr010_timer_shutdown, -	.set_state_periodic	= fttmr010_timer_set_periodic, -	.set_state_oneshot	= fttmr010_timer_shutdown, -	.tick_resume		= fttmr010_timer_shutdown, -}; -  /*   * IRQ handler for the timer   */  static irqreturn_t fttmr010_timer_interrupt(int irq, void *dev_id)  { -	struct clock_event_device *evt = &fttmr010_clockevent; +	struct clock_event_device *evt = dev_id;  	evt->event_handler(evt);  	return IRQ_HANDLED;  } -static struct irqaction fttmr010_timer_irq = { -	.name		= "Faraday FTTMR010 Timer Tick", -	.flags		= IRQF_TIMER, -	.handler	= fttmr010_timer_interrupt, -}; - -static int __init fttmr010_timer_common_init(struct device_node *np) +static int __init fttmr010_common_init(struct device_node *np, bool is_aspeed)  { +	struct fttmr010 *fttmr010;  	int irq; +	struct clk *clk; +	int ret; +	u32 val; + +	/* +	 * These implementations require a clock reference. +	 * FIXME: we currently only support clocking using PCLK +	 * and using EXTCLK is not supported in the driver. +	 */ +	clk = of_clk_get_by_name(np, "PCLK"); +	if (IS_ERR(clk)) { +		pr_err("could not get PCLK\n"); +		return PTR_ERR(clk); +	} +	ret = clk_prepare_enable(clk); +	if (ret) { +		pr_err("failed to enable PCLK\n"); +		return ret; +	} -	base = of_iomap(np, 0); -	if (!base) { +	fttmr010 = kzalloc(sizeof(*fttmr010), GFP_KERNEL); +	if (!fttmr010) { +		ret = -ENOMEM; +		goto out_disable_clock; +	} +	fttmr010->tick_rate = clk_get_rate(clk); + +	fttmr010->base = of_iomap(np, 0); +	if (!fttmr010->base) {  		pr_err("Can't remap registers"); -		return -ENXIO; +		ret = -ENXIO; +		goto out_free;  	}  	/* IRQ for timer 1 */  	irq = irq_of_parse_and_map(np, 0);  	if (irq <= 0) {  		pr_err("Can't parse IRQ"); -		return -EINVAL; +		ret = -EINVAL; +		goto out_unmap; +	} + +	/* +	 * The Aspeed AST2400 moves bits around in the control register, +	 * otherwise it works the same. +	 */ +	if (is_aspeed) { +		fttmr010->t1_enable_val = TIMER_1_CR_ASPEED_ENABLE | +			TIMER_1_CR_ASPEED_INT; +		/* Downward not available */ +		fttmr010->count_down = true; +	} else { +		fttmr010->t1_enable_val = TIMER_1_CR_ENABLE | TIMER_1_CR_INT;  	}  	/*  	 * Reset the interrupt mask and status  	 */ -	writel(TIMER_INT_ALL_MASK, base + TIMER_INTR_MASK); -	writel(0, base + TIMER_INTR_STATE); -	writel(TIMER_DEFAULT_FLAGS, base + TIMER_CR); +	writel(TIMER_INT_ALL_MASK, fttmr010->base + TIMER_INTR_MASK); +	writel(0, fttmr010->base + TIMER_INTR_STATE); + +	/* +	 * Enable timer 1 count up, timer 2 count up, except on Aspeed, +	 * where everything just counts down. +	 */ +	if (is_aspeed) +		val = TIMER_2_CR_ASPEED_ENABLE; +	else { +		val = TIMER_2_CR_ENABLE; +		if (!fttmr010->count_down) +			val |= TIMER_1_CR_UPDOWN | TIMER_2_CR_UPDOWN; +	} +	writel(val, fttmr010->base + TIMER_CR);  	/*  	 * Setup free-running clocksource timer (interrupts  	 * disabled.)  	 */ -	writel(0, base + TIMER3_COUNT); -	writel(0, base + TIMER3_LOAD); -	writel(0, base + TIMER3_MATCH1); -	writel(0, base + TIMER3_MATCH2); -	clocksource_mmio_init(base + TIMER3_COUNT, -			      "fttmr010_clocksource", tick_rate, -			      300, 32, clocksource_mmio_readl_up); -	sched_clock_register(fttmr010_read_sched_clock, 32, tick_rate); +	local_fttmr = fttmr010; +	writel(0, fttmr010->base + TIMER2_COUNT); +	writel(0, fttmr010->base + TIMER2_MATCH1); +	writel(0, fttmr010->base + TIMER2_MATCH2); + +	if (fttmr010->count_down) { +		writel(~0, fttmr010->base + TIMER2_LOAD); +		clocksource_mmio_init(fttmr010->base + TIMER2_COUNT, +				      "FTTMR010-TIMER2", +				      fttmr010->tick_rate, +				      300, 32, clocksource_mmio_readl_down); +		sched_clock_register(fttmr010_read_sched_clock_down, 32, +				     fttmr010->tick_rate); +	} else { +		writel(0, fttmr010->base + TIMER2_LOAD); +		clocksource_mmio_init(fttmr010->base + TIMER2_COUNT, +				      "FTTMR010-TIMER2", +				      fttmr010->tick_rate, +				      300, 32, clocksource_mmio_readl_up); +		sched_clock_register(fttmr010_read_sched_clock_up, 32, +				     fttmr010->tick_rate); +	}  	/* -	 * Setup clockevent timer (interrupt-driven.) +	 * Setup clockevent timer (interrupt-driven) on timer 1.  	 */ -	writel(0, base + TIMER1_COUNT); -	writel(0, base + TIMER1_LOAD); -	writel(0, base + TIMER1_MATCH1); -	writel(0, base + TIMER1_MATCH2); -	setup_irq(irq, &fttmr010_timer_irq); -	fttmr010_clockevent.cpumask = cpumask_of(0); -	clockevents_config_and_register(&fttmr010_clockevent, tick_rate, +	writel(0, fttmr010->base + TIMER1_COUNT); +	writel(0, fttmr010->base + TIMER1_LOAD); +	writel(0, fttmr010->base + TIMER1_MATCH1); +	writel(0, fttmr010->base + TIMER1_MATCH2); +	ret = request_irq(irq, fttmr010_timer_interrupt, IRQF_TIMER, +			  "FTTMR010-TIMER1", &fttmr010->clkevt); +	if (ret) { +		pr_err("FTTMR010-TIMER1 no IRQ\n"); +		goto out_unmap; +	} + +	fttmr010->clkevt.name = "FTTMR010-TIMER1"; +	/* Reasonably fast and accurate clock event */ +	fttmr010->clkevt.rating = 300; +	fttmr010->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | +		CLOCK_EVT_FEAT_ONESHOT; +	fttmr010->clkevt.set_next_event = fttmr010_timer_set_next_event; +	fttmr010->clkevt.set_state_shutdown = fttmr010_timer_shutdown; +	fttmr010->clkevt.set_state_periodic = fttmr010_timer_set_periodic; +	fttmr010->clkevt.set_state_oneshot = fttmr010_timer_set_oneshot; +	fttmr010->clkevt.tick_resume = fttmr010_timer_shutdown; +	fttmr010->clkevt.cpumask = cpumask_of(0); +	fttmr010->clkevt.irq = irq; +	clockevents_config_and_register(&fttmr010->clkevt, +					fttmr010->tick_rate,  					1, 0xffffffff); -	return 0; -} +#ifdef CONFIG_ARM +	/* Also use this timer for delays */ +	if (fttmr010->count_down) +		fttmr010->delay_timer.read_current_timer = +			fttmr010_read_current_timer_down; +	else +		fttmr010->delay_timer.read_current_timer = +			fttmr010_read_current_timer_up; +	fttmr010->delay_timer.freq = fttmr010->tick_rate; +	register_current_timer_delay(&fttmr010->delay_timer); +#endif -static int __init fttmr010_timer_of_init(struct device_node *np) -{ -	/* -	 * These implementations require a clock reference. -	 * FIXME: we currently only support clocking using PCLK -	 * and using EXTCLK is not supported in the driver. -	 */ -	struct clk *clk; +	return 0; -	clk = of_clk_get_by_name(np, "PCLK"); -	if (IS_ERR(clk)) { -		pr_err("could not get PCLK"); -		return PTR_ERR(clk); -	} -	tick_rate = clk_get_rate(clk); +out_unmap: +	iounmap(fttmr010->base); +out_free: +	kfree(fttmr010); +out_disable_clock: +	clk_disable_unprepare(clk); -	return fttmr010_timer_common_init(np); +	return ret;  } -CLOCKSOURCE_OF_DECLARE(fttmr010, "faraday,fttmr010", fttmr010_timer_of_init); -/* - * Gemini-specific: relevant registers in the global syscon - */ -#define GLOBAL_STATUS		0x04 -#define CPU_AHB_RATIO_MASK	(0x3 << 18) -#define CPU_AHB_1_1		(0x0 << 18) -#define CPU_AHB_3_2		(0x1 << 18) -#define CPU_AHB_24_13		(0x2 << 18) -#define CPU_AHB_2_1		(0x3 << 18) -#define REG_TO_AHB_SPEED(reg)	((((reg) >> 15) & 0x7) * 10 + 130) - -static int __init gemini_timer_of_init(struct device_node *np) +static __init int aspeed_timer_init(struct device_node *np)  { -	static struct regmap *map; -	int ret; -	u32 val; - -	map = syscon_regmap_lookup_by_phandle(np, "syscon"); -	if (IS_ERR(map)) { -		pr_err("Can't get regmap for syscon handle\n"); -		return -ENODEV; -	} -	ret = regmap_read(map, GLOBAL_STATUS, &val); -	if (ret) { -		pr_err("Can't read syscon status register\n"); -		return -ENXIO; -	} - -	tick_rate = REG_TO_AHB_SPEED(val) * 1000000; -	pr_info("Bus: %dMHz ", tick_rate / 1000000); - -	tick_rate /= 6;		/* APB bus run AHB*(1/6) */ - -	switch (val & CPU_AHB_RATIO_MASK) { -	case CPU_AHB_1_1: -		pr_cont("(1/1)\n"); -		break; -	case CPU_AHB_3_2: -		pr_cont("(3/2)\n"); -		break; -	case CPU_AHB_24_13: -		pr_cont("(24/13)\n"); -		break; -	case CPU_AHB_2_1: -		pr_cont("(2/1)\n"); -		break; -	} +	return fttmr010_common_init(np, true); +} -	return fttmr010_timer_common_init(np); +static __init int fttmr010_timer_init(struct device_node *np) +{ +	return fttmr010_common_init(np, false);  } -CLOCKSOURCE_OF_DECLARE(gemini, "cortina,gemini-timer", gemini_timer_of_init); + +TIMER_OF_DECLARE(fttmr010, "faraday,fttmr010", fttmr010_timer_init); +TIMER_OF_DECLARE(gemini, "cortina,gemini-timer", fttmr010_timer_init); +TIMER_OF_DECLARE(moxart, "moxa,moxart-timer", fttmr010_timer_init); +TIMER_OF_DECLARE(ast2400, "aspeed,ast2400-timer", aspeed_timer_init); +TIMER_OF_DECLARE(ast2500, "aspeed,ast2500-timer", aspeed_timer_init); diff --git a/drivers/clocksource/timer-imx-gpt.c b/drivers/clocksource/timer-imx-gpt.c index f595460bfc58..6ec6d79b237c 100644 --- a/drivers/clocksource/timer-imx-gpt.c +++ b/drivers/clocksource/timer-imx-gpt.c @@ -545,15 +545,15 @@ static int __init imx6dl_timer_init_dt(struct device_node *np)  	return mxc_timer_init_dt(np, GPT_TYPE_IMX6DL);  } -CLOCKSOURCE_OF_DECLARE(imx1_timer, "fsl,imx1-gpt", imx1_timer_init_dt); -CLOCKSOURCE_OF_DECLARE(imx21_timer, "fsl,imx21-gpt", imx21_timer_init_dt); -CLOCKSOURCE_OF_DECLARE(imx27_timer, "fsl,imx27-gpt", imx21_timer_init_dt); -CLOCKSOURCE_OF_DECLARE(imx31_timer, "fsl,imx31-gpt", imx31_timer_init_dt); -CLOCKSOURCE_OF_DECLARE(imx25_timer, "fsl,imx25-gpt", imx31_timer_init_dt); -CLOCKSOURCE_OF_DECLARE(imx50_timer, "fsl,imx50-gpt", imx31_timer_init_dt); -CLOCKSOURCE_OF_DECLARE(imx51_timer, "fsl,imx51-gpt", imx31_timer_init_dt); -CLOCKSOURCE_OF_DECLARE(imx53_timer, "fsl,imx53-gpt", imx31_timer_init_dt); -CLOCKSOURCE_OF_DECLARE(imx6q_timer, "fsl,imx6q-gpt", imx31_timer_init_dt); -CLOCKSOURCE_OF_DECLARE(imx6dl_timer, "fsl,imx6dl-gpt", imx6dl_timer_init_dt); -CLOCKSOURCE_OF_DECLARE(imx6sl_timer, "fsl,imx6sl-gpt", imx6dl_timer_init_dt); -CLOCKSOURCE_OF_DECLARE(imx6sx_timer, "fsl,imx6sx-gpt", imx6dl_timer_init_dt); +TIMER_OF_DECLARE(imx1_timer, "fsl,imx1-gpt", imx1_timer_init_dt); +TIMER_OF_DECLARE(imx21_timer, "fsl,imx21-gpt", imx21_timer_init_dt); +TIMER_OF_DECLARE(imx27_timer, "fsl,imx27-gpt", imx21_timer_init_dt); +TIMER_OF_DECLARE(imx31_timer, "fsl,imx31-gpt", imx31_timer_init_dt); +TIMER_OF_DECLARE(imx25_timer, "fsl,imx25-gpt", imx31_timer_init_dt); +TIMER_OF_DECLARE(imx50_timer, "fsl,imx50-gpt", imx31_timer_init_dt); +TIMER_OF_DECLARE(imx51_timer, "fsl,imx51-gpt", imx31_timer_init_dt); +TIMER_OF_DECLARE(imx53_timer, "fsl,imx53-gpt", imx31_timer_init_dt); +TIMER_OF_DECLARE(imx6q_timer, "fsl,imx6q-gpt", imx31_timer_init_dt); +TIMER_OF_DECLARE(imx6dl_timer, "fsl,imx6dl-gpt", imx6dl_timer_init_dt); +TIMER_OF_DECLARE(imx6sl_timer, "fsl,imx6sl-gpt", imx6dl_timer_init_dt); +TIMER_OF_DECLARE(imx6sx_timer, "fsl,imx6sx-gpt", imx6dl_timer_init_dt); diff --git a/drivers/clocksource/timer-integrator-ap.c b/drivers/clocksource/timer-integrator-ap.c index 04ad3066e190..2ff64d9d4fb3 100644 --- a/drivers/clocksource/timer-integrator-ap.c +++ b/drivers/clocksource/timer-integrator-ap.c @@ -232,5 +232,5 @@ static int __init integrator_ap_timer_init_of(struct device_node *node)  	return 0;  } -CLOCKSOURCE_OF_DECLARE(integrator_ap_timer, "arm,integrator-timer", +TIMER_OF_DECLARE(integrator_ap_timer, "arm,integrator-timer",  		       integrator_ap_timer_init_of); diff --git a/drivers/clocksource/timer-keystone.c b/drivers/clocksource/timer-keystone.c index ab68a47ab3b4..0eee03250cfc 100644 --- a/drivers/clocksource/timer-keystone.c +++ b/drivers/clocksource/timer-keystone.c @@ -226,5 +226,5 @@ err:  	return error;  } -CLOCKSOURCE_OF_DECLARE(keystone_timer, "ti,keystone-timer", +TIMER_OF_DECLARE(keystone_timer, "ti,keystone-timer",  			   keystone_timer_init); diff --git a/drivers/clocksource/timer-nps.c b/drivers/clocksource/timer-nps.c index e74ea1722ad3..7b6bb0df96ae 100644 --- a/drivers/clocksource/timer-nps.c +++ b/drivers/clocksource/timer-nps.c @@ -110,9 +110,9 @@ static int __init nps_setup_clocksource(struct device_node *node)  	return ret;  } -CLOCKSOURCE_OF_DECLARE(ezchip_nps400_clksrc, "ezchip,nps400-timer", +TIMER_OF_DECLARE(ezchip_nps400_clksrc, "ezchip,nps400-timer",  		       nps_setup_clocksource); -CLOCKSOURCE_OF_DECLARE(ezchip_nps400_clk_src, "ezchip,nps400-timer1", +TIMER_OF_DECLARE(ezchip_nps400_clk_src, "ezchip,nps400-timer1",  		       nps_setup_clocksource);  #ifdef CONFIG_EZNPS_MTM_EXT @@ -279,6 +279,6 @@ static int __init nps_setup_clockevent(struct device_node *node)  	return 0;  } -CLOCKSOURCE_OF_DECLARE(ezchip_nps400_clk_evt, "ezchip,nps400-timer0", +TIMER_OF_DECLARE(ezchip_nps400_clk_evt, "ezchip,nps400-timer0",  		       nps_setup_clockevent);  #endif /* CONFIG_EZNPS_MTM_EXT */ diff --git a/drivers/clocksource/timer-of.c b/drivers/clocksource/timer-of.c new file mode 100644 index 000000000000..f6e7491c873c --- /dev/null +++ b/drivers/clocksource/timer-of.c @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2017, Linaro Ltd.  All rights reserved. + * + * Author: Daniel Lezcano <[email protected]> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ +#include <linux/clk.h> +#include <linux/interrupt.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <linux/slab.h> + +#include "timer-of.h" + +static __init void timer_irq_exit(struct of_timer_irq *of_irq) +{ +	struct timer_of *to = container_of(of_irq, struct timer_of, of_irq); + +	struct clock_event_device *clkevt = &to->clkevt; + +	of_irq->percpu ? free_percpu_irq(of_irq->irq, clkevt) : +		free_irq(of_irq->irq, clkevt); +} + +static __init int timer_irq_init(struct device_node *np, +				 struct of_timer_irq *of_irq) +{ +	int ret; +	struct timer_of *to = container_of(of_irq, struct timer_of, of_irq); +	struct clock_event_device *clkevt = &to->clkevt; + +	of_irq->irq = of_irq->name ? of_irq_get_byname(np, of_irq->name): +		irq_of_parse_and_map(np, of_irq->index); +	if (!of_irq->irq) { +		pr_err("Failed to map interrupt for %s\n", np->full_name); +		return -EINVAL; +	} + +	ret = of_irq->percpu ? +		request_percpu_irq(of_irq->irq, of_irq->handler, +				   np->full_name, clkevt) : +		request_irq(of_irq->irq, of_irq->handler, +			    of_irq->flags ? of_irq->flags : IRQF_TIMER, +			    np->full_name, clkevt); +	if (ret) { +		pr_err("Failed to request irq %d for %s\n", of_irq->irq, +		       np->full_name); +		return ret; +	} + +	clkevt->irq = of_irq->irq; + +	return 0; +} + +static __init void timer_clk_exit(struct of_timer_clk *of_clk) +{ +	of_clk->rate = 0; +	clk_disable_unprepare(of_clk->clk); +	clk_put(of_clk->clk); +} + +static __init int timer_clk_init(struct device_node *np, +				 struct of_timer_clk *of_clk) +{ +	int ret; + +	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 %s\n", np->full_name); +		return PTR_ERR(of_clk->clk); +	} + +	ret = clk_prepare_enable(of_clk->clk); +	if (ret) { +		pr_err("Failed for enable clock for %s\n", np->full_name); +		goto out_clk_put; +	} + +	of_clk->rate = clk_get_rate(of_clk->clk); +	if (!of_clk->rate) { +		ret = -EINVAL; +		pr_err("Failed to get clock rate for %s\n", np->full_name); +		goto out_clk_disable; +	} + +	of_clk->period = DIV_ROUND_UP(of_clk->rate, HZ); +out: +	return ret; + +out_clk_disable: +	clk_disable_unprepare(of_clk->clk); +out_clk_put: +	clk_put(of_clk->clk); + +	goto out; +} + +static __init void timer_base_exit(struct of_timer_base *of_base) +{ +	iounmap(of_base->base); +} + +static __init int timer_base_init(struct device_node *np, +				  struct of_timer_base *of_base) +{ +	const char *name = of_base->name ? of_base->name : np->full_name; + +	of_base->base = of_io_request_and_map(np, of_base->index, name); +	if (!of_base->base) { +		pr_err("Failed to iomap (%s)\n", name); +		return -ENXIO; +	} + +	return 0; +} + +int __init timer_of_init(struct device_node *np, struct timer_of *to) +{ +	int ret = -EINVAL; +	int flags = 0; + +	if (to->flags & TIMER_OF_BASE) { +		ret = timer_base_init(np, &to->of_base); +		if (ret) +			goto out_fail; +		flags |= TIMER_OF_BASE; +	} + +	if (to->flags & TIMER_OF_CLOCK) { +		ret = timer_clk_init(np, &to->of_clk); +		if (ret) +			goto out_fail; +		flags |= TIMER_OF_CLOCK; +	} + +	if (to->flags & TIMER_OF_IRQ) { +		ret = timer_irq_init(np, &to->of_irq); +		if (ret) +			goto out_fail; +		flags |= TIMER_OF_IRQ; +	} + +	if (!to->clkevt.name) +		to->clkevt.name = np->name; +	return ret; + +out_fail: +	if (flags & TIMER_OF_IRQ) +		timer_irq_exit(&to->of_irq); + +	if (flags & TIMER_OF_CLOCK) +		timer_clk_exit(&to->of_clk); + +	if (flags & TIMER_OF_BASE) +		timer_base_exit(&to->of_base); +	return ret; +} diff --git a/drivers/clocksource/timer-of.h b/drivers/clocksource/timer-of.h new file mode 100644 index 000000000000..e0d727255f72 --- /dev/null +++ b/drivers/clocksource/timer-of.h @@ -0,0 +1,69 @@ +#ifndef __TIMER_OF_H__ +#define __TIMER_OF_H__ + +#include <linux/clockchips.h> + +#define TIMER_OF_BASE	0x1 +#define TIMER_OF_CLOCK	0x2 +#define TIMER_OF_IRQ	0x4 + +struct of_timer_irq { +	int irq; +	int index; +	int percpu; +	const char *name; +	unsigned long flags; +	irq_handler_t handler; +}; + +struct of_timer_base { +	void __iomem *base; +	const char *name; +	int index; +}; + +struct of_timer_clk { +	struct clk *clk; +	const char *name; +	int index; +	unsigned long rate; +	unsigned long period; +}; + +struct timer_of { +	unsigned int flags; +	struct clock_event_device clkevt; +	struct of_timer_base of_base; +	struct of_timer_irq  of_irq; +	struct of_timer_clk  of_clk; +	void *private_data; +}; + +static inline struct timer_of *to_timer_of(struct clock_event_device *clkevt) +{ +	return container_of(clkevt, struct timer_of, clkevt); +} + +static inline void __iomem *timer_of_base(struct timer_of *to) +{ +	return to->of_base.base; +} + +static inline int timer_of_irq(struct timer_of *to) +{ +	return to->of_irq.irq; +} + +static inline unsigned long timer_of_rate(struct timer_of *to) +{ +	return to->of_clk.rate; +} + +static inline unsigned long timer_of_period(struct timer_of *to) +{ +	return to->of_clk.period; +} + +extern int __init timer_of_init(struct device_node *np, +				struct timer_of *to); +#endif diff --git a/drivers/clocksource/timer-oxnas-rps.c b/drivers/clocksource/timer-oxnas-rps.c index d630bf417773..eed6feff8b5f 100644 --- a/drivers/clocksource/timer-oxnas-rps.c +++ b/drivers/clocksource/timer-oxnas-rps.c @@ -293,7 +293,7 @@ err_alloc:  	return ret;  } -CLOCKSOURCE_OF_DECLARE(ox810se_rps, +TIMER_OF_DECLARE(ox810se_rps,  		       "oxsemi,ox810se-rps-timer", oxnas_rps_timer_init); -CLOCKSOURCE_OF_DECLARE(ox820_rps, +TIMER_OF_DECLARE(ox820_rps,  		       "oxsemi,ox820se-rps-timer", oxnas_rps_timer_init); diff --git a/drivers/clocksource/timer-prima2.c b/drivers/clocksource/timer-prima2.c index b4122ed1accb..20ff33b698df 100644 --- a/drivers/clocksource/timer-prima2.c +++ b/drivers/clocksource/timer-prima2.c @@ -245,5 +245,5 @@ static int __init sirfsoc_prima2_timer_init(struct device_node *np)  	return 0;  } -CLOCKSOURCE_OF_DECLARE(sirfsoc_prima2_timer, +TIMER_OF_DECLARE(sirfsoc_prima2_timer,  	"sirf,prima2-tick", sirfsoc_prima2_timer_init); diff --git a/drivers/clocksource/clksrc-probe.c b/drivers/clocksource/timer-probe.c index ac701ffb8d59..da81e5de74fe 100644 --- a/drivers/clocksource/clksrc-probe.c +++ b/drivers/clocksource/timer-probe.c @@ -19,20 +19,20 @@  #include <linux/of.h>  #include <linux/clocksource.h> -extern struct of_device_id __clksrc_of_table[]; +extern struct of_device_id __timer_of_table[]; -static const struct of_device_id __clksrc_of_table_sentinel -	__used __section(__clksrc_of_table_end); +static const struct of_device_id __timer_of_table_sentinel +	__used __section(__timer_of_table_end); -void __init clocksource_probe(void) +void __init timer_probe(void)  {  	struct device_node *np;  	const struct of_device_id *match;  	of_init_fn_1_ret init_func_ret; -	unsigned clocksources = 0; +	unsigned timers = 0;  	int ret; -	for_each_matching_node_and_match(np, __clksrc_of_table, &match) { +	for_each_matching_node_and_match(np, __timer_of_table, &match) {  		if (!of_device_is_available(np))  			continue; @@ -45,11 +45,11 @@ void __init clocksource_probe(void)  			continue;  		} -		clocksources++; +		timers++;  	} -	clocksources += acpi_probe_device_table(clksrc); +	timers += acpi_probe_device_table(timer); -	if (!clocksources) -		pr_crit("%s: no matching clocksources found\n", __func__); +	if (!timers) +		pr_crit("%s: no matching timers found\n", __func__);  } diff --git a/drivers/clocksource/timer-sp804.c b/drivers/clocksource/timer-sp804.c index 2d575a8c0939..3ac9dec9a038 100644 --- a/drivers/clocksource/timer-sp804.c +++ b/drivers/clocksource/timer-sp804.c @@ -287,7 +287,7 @@ err:  	iounmap(base);  	return ret;  } -CLOCKSOURCE_OF_DECLARE(sp804, "arm,sp804", sp804_of_init); +TIMER_OF_DECLARE(sp804, "arm,sp804", sp804_of_init);  static int __init integrator_cp_of_init(struct device_node *np)  { @@ -335,4 +335,4 @@ err:  	iounmap(base);  	return ret;  } -CLOCKSOURCE_OF_DECLARE(intcp, "arm,integrator-cp-timer", integrator_cp_of_init); +TIMER_OF_DECLARE(intcp, "arm,integrator-cp-timer", integrator_cp_of_init); diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c index 1b2574c4fb97..174d1243ea93 100644 --- a/drivers/clocksource/timer-stm32.c +++ b/drivers/clocksource/timer-stm32.c @@ -187,4 +187,4 @@ err_clk_get:  	return ret;  } -CLOCKSOURCE_OF_DECLARE(stm32, "st,stm32-timer", stm32_clockevent_init); +TIMER_OF_DECLARE(stm32, "st,stm32-timer", stm32_clockevent_init); diff --git a/drivers/clocksource/timer-sun5i.c b/drivers/clocksource/timer-sun5i.c index c4656c4d44a6..2a3fe83ec337 100644 --- a/drivers/clocksource/timer-sun5i.c +++ b/drivers/clocksource/timer-sun5i.c @@ -359,7 +359,7 @@ static int __init sun5i_timer_init(struct device_node *node)  	return sun5i_setup_clockevent(node, timer_base, clk, irq);  } -CLOCKSOURCE_OF_DECLARE(sun5i_a13, "allwinner,sun5i-a13-hstimer", +TIMER_OF_DECLARE(sun5i_a13, "allwinner,sun5i-a13-hstimer",  			   sun5i_timer_init); -CLOCKSOURCE_OF_DECLARE(sun7i_a20, "allwinner,sun7i-a20-hstimer", +TIMER_OF_DECLARE(sun7i_a20, "allwinner,sun7i-a20-hstimer",  			   sun5i_timer_init); diff --git a/drivers/clocksource/timer-ti-32k.c b/drivers/clocksource/timer-ti-32k.c index 624067712ef0..880a861ab3c8 100644 --- a/drivers/clocksource/timer-ti-32k.c +++ b/drivers/clocksource/timer-ti-32k.c @@ -124,5 +124,5 @@ static int __init ti_32k_timer_init(struct device_node *np)  	return 0;  } -CLOCKSOURCE_OF_DECLARE(ti_32k_timer, "ti,omap-counter32k", +TIMER_OF_DECLARE(ti_32k_timer, "ti,omap-counter32k",  		ti_32k_timer_init); diff --git a/drivers/clocksource/timer-u300.c b/drivers/clocksource/timer-u300.c index 704e40c6f151..be34b116d4d2 100644 --- a/drivers/clocksource/timer-u300.c +++ b/drivers/clocksource/timer-u300.c @@ -458,5 +458,5 @@ static int __init u300_timer_init_of(struct device_node *np)  	return 0;  } -CLOCKSOURCE_OF_DECLARE(u300_timer, "stericsson,u300-apptimer", +TIMER_OF_DECLARE(u300_timer, "stericsson,u300-apptimer",  		       u300_timer_init_of); diff --git a/drivers/clocksource/versatile.c b/drivers/clocksource/versatile.c index 220b490a8142..39725d38aede 100644 --- a/drivers/clocksource/versatile.c +++ b/drivers/clocksource/versatile.c @@ -38,7 +38,7 @@ static int __init versatile_sched_clock_init(struct device_node *node)  	return 0;  } -CLOCKSOURCE_OF_DECLARE(vexpress, "arm,vexpress-sysreg", +TIMER_OF_DECLARE(vexpress, "arm,vexpress-sysreg",  		       versatile_sched_clock_init); -CLOCKSOURCE_OF_DECLARE(versatile, "arm,versatile-sysreg", +TIMER_OF_DECLARE(versatile, "arm,versatile-sysreg",  		       versatile_sched_clock_init); diff --git a/drivers/clocksource/vf_pit_timer.c b/drivers/clocksource/vf_pit_timer.c index e0849e20a307..0f92089ec08c 100644 --- a/drivers/clocksource/vf_pit_timer.c +++ b/drivers/clocksource/vf_pit_timer.c @@ -201,4 +201,4 @@ static int __init pit_timer_init(struct device_node *np)  	return pit_clockevent_init(clk_rate, irq);  } -CLOCKSOURCE_OF_DECLARE(vf610, "fsl,vf610-pit", pit_timer_init); +TIMER_OF_DECLARE(vf610, "fsl,vf610-pit", pit_timer_init); diff --git a/drivers/clocksource/vt8500_timer.c b/drivers/clocksource/vt8500_timer.c index d02b51075ad1..e0f7489cfc8e 100644 --- a/drivers/clocksource/vt8500_timer.c +++ b/drivers/clocksource/vt8500_timer.c @@ -165,4 +165,4 @@ static int __init vt8500_timer_init(struct device_node *np)  	return 0;  } -CLOCKSOURCE_OF_DECLARE(vt8500, "via,vt8500-timer", vt8500_timer_init); +TIMER_OF_DECLARE(vt8500, "via,vt8500-timer", vt8500_timer_init); diff --git a/drivers/clocksource/zevio-timer.c b/drivers/clocksource/zevio-timer.c index 9a53f5ef6157..a6a0338eea77 100644 --- a/drivers/clocksource/zevio-timer.c +++ b/drivers/clocksource/zevio-timer.c @@ -215,4 +215,4 @@ static int __init zevio_timer_init(struct device_node *node)  	return zevio_timer_add(node);  } -CLOCKSOURCE_OF_DECLARE(zevio_timer, "lsi,zevio-timer", zevio_timer_init); +TIMER_OF_DECLARE(zevio_timer, "lsi,zevio-timer", zevio_timer_init); diff --git a/include/asm-generic/siginfo.h b/include/asm-generic/siginfo.h deleted file mode 100644 index a2508a8f9a9c..000000000000 --- a/include/asm-generic/siginfo.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _ASM_GENERIC_SIGINFO_H -#define _ASM_GENERIC_SIGINFO_H - -#include <uapi/asm-generic/siginfo.h> - -#define __SI_MASK	0xffff0000u -#define __SI_KILL	(0 << 16) -#define __SI_TIMER	(1 << 16) -#define __SI_POLL	(2 << 16) -#define __SI_FAULT	(3 << 16) -#define __SI_CHLD	(4 << 16) -#define __SI_RT		(5 << 16) -#define __SI_MESGQ	(6 << 16) -#define __SI_SYS	(7 << 16) -#define __SI_CODE(T,N)	((T) | ((N) & 0xffff)) - -struct siginfo; -void do_schedule_next_timer(struct siginfo *info); - -extern int copy_siginfo_to_user(struct siginfo __user *to, const struct siginfo *from); - -#endif diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 314a0b9219c6..0d64658a224f 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -172,8 +172,7 @@  	KEEP(*(__##name##_of_table))					\  	KEEP(*(__##name##_of_table_end)) -#define CLKSRC_OF_TABLES()	OF_TABLE(CONFIG_CLKSRC_OF, clksrc) -#define CLKEVT_OF_TABLES()	OF_TABLE(CONFIG_CLKEVT_OF, clkevt) +#define TIMER_OF_TABLES()	OF_TABLE(CONFIG_TIMER_OF, timer)  #define IRQCHIP_OF_MATCH_TABLE() OF_TABLE(CONFIG_IRQCHIP, irqchip)  #define CLK_OF_TABLES()		OF_TABLE(CONFIG_COMMON_CLK, clk)  #define IOMMU_OF_TABLES()	OF_TABLE(CONFIG_OF_IOMMU, iommu) @@ -557,15 +556,15 @@  	MEM_DISCARD(init.rodata)					\  	CLK_OF_TABLES()							\  	RESERVEDMEM_OF_TABLES()						\ -	CLKSRC_OF_TABLES()						\ -	CLKEVT_OF_TABLES()						\ +	TIMER_OF_TABLES()						\  	IOMMU_OF_TABLES()						\  	CPU_METHOD_OF_TABLES()						\  	CPUIDLE_METHOD_OF_TABLES()					\  	KERNEL_DTB()							\  	IRQCHIP_OF_MATCH_TABLE()					\  	ACPI_PROBE_TABLE(irqchip)					\ -	ACPI_PROBE_TABLE(clksrc)					\ +	ACPI_PROBE_TABLE(timer)						\ +	ACPI_PROBE_TABLE(iort)						\  	EARLYCON_TABLE()  #define INIT_TEXT							\ diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h index acc9ce05e5f0..a116926598fd 100644 --- a/include/linux/clockchips.h +++ b/include/linux/clockchips.h @@ -223,13 +223,4 @@ static inline void tick_setup_hrtimer_broadcast(void) { }  #endif /* !CONFIG_GENERIC_CLOCKEVENTS */ -#define CLOCKEVENT_OF_DECLARE(name, compat, fn) \ -	OF_DECLARE_1_RET(clkevt, name, compat, fn) - -#ifdef CONFIG_CLKEVT_PROBE -extern int clockevent_probe(void); -#else -static inline int clockevent_probe(void) { return 0; } -#endif -  #endif /* _LINUX_CLOCKCHIPS_H */ diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h index 81490456c242..a78cb1848e65 100644 --- a/include/linux/clocksource.h +++ b/include/linux/clocksource.h @@ -250,16 +250,19 @@ extern int clocksource_mmio_init(void __iomem *, const char *,  extern int clocksource_i8253_init(void); +#define TIMER_OF_DECLARE(name, compat, fn) \ +	OF_DECLARE_1_RET(timer, name, compat, fn) +  #define CLOCKSOURCE_OF_DECLARE(name, compat, fn) \ -	OF_DECLARE_1_RET(clksrc, name, compat, fn) +	TIMER_OF_DECLARE(name, compat, fn) -#ifdef CONFIG_CLKSRC_PROBE -extern void clocksource_probe(void); +#ifdef CONFIG_TIMER_PROBE +extern void timer_probe(void);  #else -static inline void clocksource_probe(void) {} +static inline void timer_probe(void) {}  #endif -#define CLOCKSOURCE_ACPI_DECLARE(name, table_id, fn)		\ -	ACPI_DECLARE_PROBE_ENTRY(clksrc, name, table_id, 0, NULL, 0, fn) +#define TIMER_ACPI_DECLARE(name, table_id, fn)		\ +	ACPI_DECLARE_PROBE_ENTRY(timer, name, table_id, 0, NULL, 0, fn)  #endif /* _LINUX_CLOCKSOURCE_H */ diff --git a/include/linux/compat.h b/include/linux/compat.h index 1c5f3152cbb5..425563c7647b 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -94,6 +94,10 @@ struct compat_itimerval {  	struct compat_timeval	it_value;  }; +struct itimerval; +int get_compat_itimerval(struct itimerval *, const struct compat_itimerval __user *); +int put_compat_itimerval(struct compat_itimerval __user *, const struct itimerval *); +  struct compat_tms {  	compat_clock_t		tms_utime;  	compat_clock_t		tms_stime; @@ -128,6 +132,10 @@ struct compat_timex {  	compat_int_t:32; compat_int_t:32; compat_int_t:32;  }; +struct timex; +int compat_get_timex(struct timex *, const struct compat_timex __user *); +int compat_put_timex(struct compat_timex __user *, const struct timex *); +  #define _COMPAT_NSIG_WORDS	(_COMPAT_NSIG / _COMPAT_NSIG_BPW)  typedef struct { diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index 8c5b10eb7265..255edd5e7a74 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h @@ -452,11 +452,11 @@ static inline u64 hrtimer_forward_now(struct hrtimer *timer,  }  /* Precise sleep: */ -extern long hrtimer_nanosleep(struct timespec64 *rqtp, -			      struct timespec __user *rmtp, + +extern int nanosleep_copyout(struct restart_block *, struct timespec *); +extern long hrtimer_nanosleep(const struct timespec64 *rqtp,  			      const enum hrtimer_mode mode,  			      const clockid_t clockid); -extern long hrtimer_nanosleep_restart(struct restart_block *restart_block);  extern void hrtimer_init_sleeper(struct hrtimer_sleeper *sl,  				 struct task_struct *tsk); diff --git a/include/linux/posix-clock.h b/include/linux/posix-clock.h index 83b22ae9ae12..38d8225510f1 100644 --- a/include/linux/posix-clock.h +++ b/include/linux/posix-clock.h @@ -42,12 +42,6 @@ struct posix_clock;   * @clock_gettime:  Read the current time   * @clock_getres:   Get the clock resolution   * @clock_settime:  Set the current time value - * @timer_create:   Create a new timer - * @timer_delete:   Remove a previously created timer - * @timer_gettime:  Get remaining time and interval of a timer - * @timer_settime: Set a timer's initial expiration and interval - * @fasync:         Optional character device fasync method - * @mmap:           Optional character device mmap method   * @open:           Optional character device open method   * @release:        Optional character device release method   * @ioctl:          Optional character device ioctl method @@ -66,28 +60,12 @@ struct posix_clock_operations {  	int  (*clock_settime)(struct posix_clock *pc,  			      const struct timespec64 *ts); -	int  (*timer_create) (struct posix_clock *pc, struct k_itimer *kit); - -	int  (*timer_delete) (struct posix_clock *pc, struct k_itimer *kit); - -	void (*timer_gettime)(struct posix_clock *pc, -			      struct k_itimer *kit, struct itimerspec64 *tsp); - -	int  (*timer_settime)(struct posix_clock *pc, -			      struct k_itimer *kit, int flags, -			      struct itimerspec64 *tsp, struct itimerspec64 *old);  	/*  	 * Optional character device methods:  	 */ -	int     (*fasync)  (struct posix_clock *pc, -			    int fd, struct file *file, int on); -  	long    (*ioctl)   (struct posix_clock *pc,  			    unsigned int cmd, unsigned long arg); -	int     (*mmap)    (struct posix_clock *pc, -			    struct vm_area_struct *vma); -  	int     (*open)    (struct posix_clock *pc, fmode_t f_mode);  	uint    (*poll)    (struct posix_clock *pc, diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h index 8c1e43ab14a9..29f1b7f09ced 100644 --- a/include/linux/posix-timers.h +++ b/include/linux/posix-timers.h @@ -7,6 +7,7 @@  #include <linux/timex.h>  #include <linux/alarmtimer.h> +struct siginfo;  struct cpu_timer_list {  	struct list_head entry; @@ -48,81 +49,69 @@ struct cpu_timer_list {  #define FD_TO_CLOCKID(fd)	((~(clockid_t) (fd) << 3) | CLOCKFD)  #define CLOCKID_TO_FD(clk)	((unsigned int) ~((clk) >> 3)) -/* POSIX.1b interval timer structure. */ -struct k_itimer { -	struct list_head list;		/* free/ allocate list */ -	struct hlist_node t_hash; -	spinlock_t it_lock; -	clockid_t it_clock;		/* which timer type */ -	timer_t it_id;			/* timer id */ -	int it_overrun;			/* overrun on pending signal  */ -	int it_overrun_last;		/* overrun on last delivered signal */ -	int it_requeue_pending;		/* waiting to requeue this timer */  #define REQUEUE_PENDING 1 -	int it_sigev_notify;		/* notify word of sigevent struct */ -	struct signal_struct *it_signal; + +/** + * struct k_itimer - POSIX.1b interval timer structure. + * @list:		List head for binding the timer to signals->posix_timers + * @t_hash:		Entry in the posix timer hash table + * @it_lock:		Lock protecting the timer + * @kclock:		Pointer to the k_clock struct handling this timer + * @it_clock:		The posix timer clock id + * @it_id:		The posix timer id for identifying the timer + * @it_active:		Marker that timer is active + * @it_overrun:		The overrun counter for pending signals + * @it_overrun_last:	The overrun at the time of the last delivered signal + * @it_requeue_pending:	Indicator that timer waits for being requeued on + *			signal delivery + * @it_sigev_notify:	The notify word of sigevent struct for signal delivery + * @it_interval:	The interval for periodic timers + * @it_signal:		Pointer to the creators signal struct + * @it_pid:		The pid of the process/task targeted by the signal + * @it_process:		The task to wakeup on clock_nanosleep (CPU timers) + * @sigq:		Pointer to preallocated sigqueue + * @it:			Union representing the various posix timer type + *			internals. Also used for rcu freeing the timer. + */ +struct k_itimer { +	struct list_head	list; +	struct hlist_node	t_hash; +	spinlock_t		it_lock; +	const struct k_clock	*kclock; +	clockid_t		it_clock; +	timer_t			it_id; +	int			it_active; +	int			it_overrun; +	int			it_overrun_last; +	int			it_requeue_pending; +	int			it_sigev_notify; +	ktime_t			it_interval; +	struct signal_struct	*it_signal;  	union { -		struct pid *it_pid;	/* pid of process to send signal to */ -		struct task_struct *it_process;	/* for clock_nanosleep */ +		struct pid		*it_pid; +		struct task_struct	*it_process;  	}; -	struct sigqueue *sigq;		/* signal queue entry. */ +	struct sigqueue		*sigq;  	union {  		struct { -			struct hrtimer timer; -			ktime_t interval; +			struct hrtimer	timer;  		} real; -		struct cpu_timer_list cpu; +		struct cpu_timer_list	cpu;  		struct { -			unsigned int clock; -			unsigned int node; -			unsigned long incr; -			unsigned long expires; -		} mmtimer; -		struct { -			struct alarm alarmtimer; -			ktime_t interval; +			struct alarm	alarmtimer;  		} alarm; -		struct rcu_head rcu; +		struct rcu_head		rcu;  	} it;  }; -struct k_clock { -	int (*clock_getres) (const clockid_t which_clock, struct timespec64 *tp); -	int (*clock_set) (const clockid_t which_clock, -			  const struct timespec64 *tp); -	int (*clock_get) (const clockid_t which_clock, struct timespec64 *tp); -	int (*clock_adj) (const clockid_t which_clock, struct timex *tx); -	int (*timer_create) (struct k_itimer *timer); -	int (*nsleep) (const clockid_t which_clock, int flags, -		       struct timespec64 *, struct timespec __user *); -	long (*nsleep_restart) (struct restart_block *restart_block); -	int (*timer_set) (struct k_itimer *timr, int flags, -			  struct itimerspec64 *new_setting, -			  struct itimerspec64 *old_setting); -	int (*timer_del) (struct k_itimer *timr); -#define TIMER_RETRY 1 -	void (*timer_get) (struct k_itimer *timr, -			   struct itimerspec64 *cur_setting); -}; - -extern struct k_clock clock_posix_cpu; -extern struct k_clock clock_posix_dynamic; - -void posix_timers_register_clock(const clockid_t clock_id, struct k_clock *new_clock); - -/* function to call to trigger timer event */ -int posix_timer_event(struct k_itimer *timr, int si_private); - -void posix_cpu_timer_schedule(struct k_itimer *timer); -  void run_posix_cpu_timers(struct task_struct *task);  void posix_cpu_timers_exit(struct task_struct *task);  void posix_cpu_timers_exit_group(struct task_struct *task);  void set_process_cpu_timer(struct task_struct *task, unsigned int clock_idx,  			   u64 *newval, u64 *oldval); -long clock_nanosleep_restart(struct restart_block *restart_block); -  void update_rlimit_cpu(struct task_struct *task, unsigned long rlim_new); +void posixtimer_rearm(struct siginfo *info); +  #endif diff --git a/include/linux/restart_block.h b/include/linux/restart_block.h index 0d905d8ec553..19df8422606c 100644 --- a/include/linux/restart_block.h +++ b/include/linux/restart_block.h @@ -11,6 +11,14 @@ struct timespec;  struct compat_timespec;  struct pollfd; +enum timespec_type { +	TT_NONE		= 0, +	TT_NATIVE	= 1, +#ifdef CONFIG_COMPAT +	TT_COMPAT	= 2, +#endif +}; +  /*   * System call restart block.   */ @@ -29,10 +37,13 @@ struct restart_block {  		/* For nanosleep */  		struct {  			clockid_t clockid; -			struct timespec __user *rmtp; +			enum timespec_type type; +			union { +				struct timespec __user *rmtp;  #ifdef CONFIG_COMPAT -			struct compat_timespec __user *compat_rmtp; +				struct compat_timespec __user *compat_rmtp;  #endif +			};  			u64 expires;  		} nanosleep;  		/* For poll */ diff --git a/include/linux/signal.h b/include/linux/signal.h index 1f5a16620693..a39feddd71ba 100644 --- a/include/linux/signal.h +++ b/include/linux/signal.h @@ -3,16 +3,13 @@  #include <linux/bug.h>  #include <linux/signal_types.h> +#include <linux/string.h>  struct task_struct;  /* for sysctl */  extern int print_fatal_signals; -#ifndef HAVE_ARCH_COPY_SIGINFO - -#include <linux/string.h> -  static inline void copy_siginfo(struct siginfo *to, struct siginfo *from)  {  	if (from->si_code < 0) @@ -22,7 +19,7 @@ static inline void copy_siginfo(struct siginfo *to, struct siginfo *from)  		memcpy(to, from, __ARCH_SI_PREAMBLE_SIZE + sizeof(from->_sifields._sigchld));  } -#endif +int copy_siginfo_to_user(struct siginfo __user *to, const struct siginfo *from);  /*   * Define some primitives to manipulate sigset_t. diff --git a/include/linux/timekeeper_internal.h b/include/linux/timekeeper_internal.h index f7043ccca81c..0a0a53daf2a2 100644 --- a/include/linux/timekeeper_internal.h +++ b/include/linux/timekeeper_internal.h @@ -51,7 +51,7 @@ struct tk_read_base {   * @clock_was_set_seq:	The sequence number of clock was set events   * @cs_was_changed_seq:	The sequence number of clocksource change events   * @next_leap_ktime:	CLOCK_MONOTONIC time value of a pending leap-second - * @raw_time:		Monotonic raw base time in timespec64 format + * @raw_sec:		CLOCK_MONOTONIC_RAW  time in seconds   * @cycle_interval:	Number of clock cycles in one NTP interval   * @xtime_interval:	Number of clock shifted nano seconds in one NTP   *			interval. @@ -93,7 +93,7 @@ struct timekeeper {  	unsigned int		clock_was_set_seq;  	u8			cs_was_changed_seq;  	ktime_t			next_leap_ktime; -	struct timespec64	raw_time; +	u64			raw_sec;  	/* The following members are for timekeeping internal use */  	u64			cycle_interval; diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h index 1abaf62c86fc..9c4eca6b374a 100644 --- a/include/uapi/asm-generic/siginfo.h +++ b/include/uapi/asm-generic/siginfo.h @@ -151,7 +151,18 @@ typedef struct siginfo {  #define si_arch		_sifields._sigsys._arch  #endif -#ifndef __KERNEL__ +#ifdef __KERNEL__ +#define __SI_MASK	0xffff0000u +#define __SI_KILL	(0 << 16) +#define __SI_TIMER	(1 << 16) +#define __SI_POLL	(2 << 16) +#define __SI_FAULT	(3 << 16) +#define __SI_CHLD	(4 << 16) +#define __SI_RT		(5 << 16) +#define __SI_MESGQ	(6 << 16) +#define __SI_SYS	(7 << 16) +#define __SI_CODE(T,N)	((T) | ((N) & 0xffff)) +#else /* __KERNEL__ */  #define __SI_KILL	0  #define __SI_TIMER	0  #define __SI_POLL	0 @@ -161,7 +172,7 @@ typedef struct siginfo {  #define __SI_MESGQ	0  #define __SI_SYS	0  #define __SI_CODE(T,N)	(N) -#endif +#endif /* __KERNEL__ */  /*   * si_code values diff --git a/include/uapi/linux/time.h b/include/uapi/linux/time.h index e75e1b6ff27f..09299fcb842a 100644 --- a/include/uapi/linux/time.h +++ b/include/uapi/linux/time.h @@ -54,7 +54,11 @@ struct itimerval {  #define CLOCK_BOOTTIME			7  #define CLOCK_REALTIME_ALARM		8  #define CLOCK_BOOTTIME_ALARM		9 -#define CLOCK_SGI_CYCLE			10	/* Hardware specific */ +/* + * The driver implementing this got removed. The clock ID is kept as a + * place holder. Do not reuse! + */ +#define CLOCK_SGI_CYCLE			10  #define CLOCK_TAI			11  #define MAX_CLOCKS			16 diff --git a/kernel/compat.c b/kernel/compat.c index 933bcb31ae10..ebd8bdc3fd68 100644 --- a/kernel/compat.c +++ b/kernel/compat.c @@ -30,100 +30,66 @@  #include <linux/uaccess.h> -static int compat_get_timex(struct timex *txc, struct compat_timex __user *utp) +int compat_get_timex(struct timex *txc, const struct compat_timex __user *utp)  { -	memset(txc, 0, sizeof(struct timex)); - -	if (!access_ok(VERIFY_READ, utp, sizeof(struct compat_timex)) || -			__get_user(txc->modes, &utp->modes) || -			__get_user(txc->offset, &utp->offset) || -			__get_user(txc->freq, &utp->freq) || -			__get_user(txc->maxerror, &utp->maxerror) || -			__get_user(txc->esterror, &utp->esterror) || -			__get_user(txc->status, &utp->status) || -			__get_user(txc->constant, &utp->constant) || -			__get_user(txc->precision, &utp->precision) || -			__get_user(txc->tolerance, &utp->tolerance) || -			__get_user(txc->time.tv_sec, &utp->time.tv_sec) || -			__get_user(txc->time.tv_usec, &utp->time.tv_usec) || -			__get_user(txc->tick, &utp->tick) || -			__get_user(txc->ppsfreq, &utp->ppsfreq) || -			__get_user(txc->jitter, &utp->jitter) || -			__get_user(txc->shift, &utp->shift) || -			__get_user(txc->stabil, &utp->stabil) || -			__get_user(txc->jitcnt, &utp->jitcnt) || -			__get_user(txc->calcnt, &utp->calcnt) || -			__get_user(txc->errcnt, &utp->errcnt) || -			__get_user(txc->stbcnt, &utp->stbcnt)) -		return -EFAULT; +	struct compat_timex tx32; -	return 0; -} - -static int compat_put_timex(struct compat_timex __user *utp, struct timex *txc) -{ -	if (!access_ok(VERIFY_WRITE, utp, sizeof(struct compat_timex)) || -			__put_user(txc->modes, &utp->modes) || -			__put_user(txc->offset, &utp->offset) || -			__put_user(txc->freq, &utp->freq) || -			__put_user(txc->maxerror, &utp->maxerror) || -			__put_user(txc->esterror, &utp->esterror) || -			__put_user(txc->status, &utp->status) || -			__put_user(txc->constant, &utp->constant) || -			__put_user(txc->precision, &utp->precision) || -			__put_user(txc->tolerance, &utp->tolerance) || -			__put_user(txc->time.tv_sec, &utp->time.tv_sec) || -			__put_user(txc->time.tv_usec, &utp->time.tv_usec) || -			__put_user(txc->tick, &utp->tick) || -			__put_user(txc->ppsfreq, &utp->ppsfreq) || -			__put_user(txc->jitter, &utp->jitter) || -			__put_user(txc->shift, &utp->shift) || -			__put_user(txc->stabil, &utp->stabil) || -			__put_user(txc->jitcnt, &utp->jitcnt) || -			__put_user(txc->calcnt, &utp->calcnt) || -			__put_user(txc->errcnt, &utp->errcnt) || -			__put_user(txc->stbcnt, &utp->stbcnt) || -			__put_user(txc->tai, &utp->tai)) +	if (copy_from_user(&tx32, utp, sizeof(struct compat_timex)))  		return -EFAULT; -	return 0; -} -COMPAT_SYSCALL_DEFINE2(gettimeofday, struct compat_timeval __user *, tv, -		       struct timezone __user *, tz) -{ -	if (tv) { -		struct timeval ktv; -		do_gettimeofday(&ktv); -		if (compat_put_timeval(&ktv, tv)) -			return -EFAULT; -	} -	if (tz) { -		if (copy_to_user(tz, &sys_tz, sizeof(sys_tz))) -			return -EFAULT; -	} +	txc->modes = tx32.modes; +	txc->offset = tx32.offset; +	txc->freq = tx32.freq; +	txc->maxerror = tx32.maxerror; +	txc->esterror = tx32.esterror; +	txc->status = tx32.status; +	txc->constant = tx32.constant; +	txc->precision = tx32.precision; +	txc->tolerance = tx32.tolerance; +	txc->time.tv_sec = tx32.time.tv_sec; +	txc->time.tv_usec = tx32.time.tv_usec; +	txc->tick = tx32.tick; +	txc->ppsfreq = tx32.ppsfreq; +	txc->jitter = tx32.jitter; +	txc->shift = tx32.shift; +	txc->stabil = tx32.stabil; +	txc->jitcnt = tx32.jitcnt; +	txc->calcnt = tx32.calcnt; +	txc->errcnt = tx32.errcnt; +	txc->stbcnt = tx32.stbcnt;  	return 0;  } -COMPAT_SYSCALL_DEFINE2(settimeofday, struct compat_timeval __user *, tv, -		       struct timezone __user *, tz) -{ -	struct timespec64 new_ts; -	struct timeval user_tv; -	struct timezone new_tz; - -	if (tv) { -		if (compat_get_timeval(&user_tv, tv)) -			return -EFAULT; -		new_ts.tv_sec = user_tv.tv_sec; -		new_ts.tv_nsec = user_tv.tv_usec * NSEC_PER_USEC; -	} -	if (tz) { -		if (copy_from_user(&new_tz, tz, sizeof(*tz))) -			return -EFAULT; -	} - -	return do_sys_settimeofday64(tv ? &new_ts : NULL, tz ? &new_tz : NULL); +int compat_put_timex(struct compat_timex __user *utp, const struct timex *txc) +{ +	struct compat_timex tx32; + +	memset(&tx32, 0, sizeof(struct compat_timex)); +	tx32.modes = txc->modes; +	tx32.offset = txc->offset; +	tx32.freq = txc->freq; +	tx32.maxerror = txc->maxerror; +	tx32.esterror = txc->esterror; +	tx32.status = txc->status; +	tx32.constant = txc->constant; +	tx32.precision = txc->precision; +	tx32.tolerance = txc->tolerance; +	tx32.time.tv_sec = txc->time.tv_sec; +	tx32.time.tv_usec = txc->time.tv_usec; +	tx32.tick = txc->tick; +	tx32.ppsfreq = txc->ppsfreq; +	tx32.jitter = txc->jitter; +	tx32.shift = txc->shift; +	tx32.stabil = txc->stabil; +	tx32.jitcnt = txc->jitcnt; +	tx32.calcnt = txc->calcnt; +	tx32.errcnt = txc->errcnt; +	tx32.stbcnt = txc->stbcnt; +	tx32.tai = txc->tai; +	if (copy_to_user(utp, &tx32, sizeof(struct compat_timex))) +		return -EFAULT; +	return 0;  }  static int __compat_get_timeval(struct timeval *tv, const struct compat_timeval __user *ctv) @@ -213,141 +179,28 @@ int compat_convert_timespec(struct timespec __user **kts,  	return 0;  } -static long compat_nanosleep_restart(struct restart_block *restart) -{ -	struct compat_timespec __user *rmtp; -	struct timespec rmt; -	mm_segment_t oldfs; -	long ret; - -	restart->nanosleep.rmtp = (struct timespec __user *) &rmt; -	oldfs = get_fs(); -	set_fs(KERNEL_DS); -	ret = hrtimer_nanosleep_restart(restart); -	set_fs(oldfs); - -	if (ret == -ERESTART_RESTARTBLOCK) { -		rmtp = restart->nanosleep.compat_rmtp; - -		if (rmtp && compat_put_timespec(&rmt, rmtp)) -			return -EFAULT; -	} - -	return ret; -} - -COMPAT_SYSCALL_DEFINE2(nanosleep, struct compat_timespec __user *, rqtp, -		       struct compat_timespec __user *, rmtp) +int get_compat_itimerval(struct itimerval *o, const struct compat_itimerval __user *i)  { -	struct timespec tu, rmt; -	struct timespec64 tu64; -	mm_segment_t oldfs; -	long ret; +	struct compat_itimerval v32; -	if (compat_get_timespec(&tu, rqtp)) +	if (copy_from_user(&v32, i, sizeof(struct compat_itimerval)))  		return -EFAULT; - -	tu64 = timespec_to_timespec64(tu); -	if (!timespec64_valid(&tu64)) -		return -EINVAL; - -	oldfs = get_fs(); -	set_fs(KERNEL_DS); -	ret = hrtimer_nanosleep(&tu64, -				rmtp ? (struct timespec __user *)&rmt : NULL, -				HRTIMER_MODE_REL, CLOCK_MONOTONIC); -	set_fs(oldfs); - -	/* -	 * hrtimer_nanosleep() can only return 0 or -	 * -ERESTART_RESTARTBLOCK here because: -	 * -	 * - we call it with HRTIMER_MODE_REL and therefor exclude the -	 *   -ERESTARTNOHAND return path. -	 * -	 * - we supply the rmtp argument from the task stack (due to -	 *   the necessary compat conversion. So the update cannot -	 *   fail, which excludes the -EFAULT return path as well. If -	 *   it fails nevertheless we have a bigger problem and wont -	 *   reach this place anymore. -	 * -	 * - if the return value is 0, we do not have to update rmtp -	 *    because there is no remaining time. -	 * -	 * We check for -ERESTART_RESTARTBLOCK nevertheless if the -	 * core implementation decides to return random nonsense. -	 */ -	if (ret == -ERESTART_RESTARTBLOCK) { -		struct restart_block *restart = ¤t->restart_block; - -		restart->fn = compat_nanosleep_restart; -		restart->nanosleep.compat_rmtp = rmtp; - -		if (rmtp && compat_put_timespec(&rmt, rmtp)) -			return -EFAULT; -	} -	return ret; -} - -static inline long get_compat_itimerval(struct itimerval *o, -		struct compat_itimerval __user *i) -{ -	return (!access_ok(VERIFY_READ, i, sizeof(*i)) || -		(__get_user(o->it_interval.tv_sec, &i->it_interval.tv_sec) | -		 __get_user(o->it_interval.tv_usec, &i->it_interval.tv_usec) | -		 __get_user(o->it_value.tv_sec, &i->it_value.tv_sec) | -		 __get_user(o->it_value.tv_usec, &i->it_value.tv_usec))); -} - -static inline long put_compat_itimerval(struct compat_itimerval __user *o, -		struct itimerval *i) -{ -	return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) || -		(__put_user(i->it_interval.tv_sec, &o->it_interval.tv_sec) | -		 __put_user(i->it_interval.tv_usec, &o->it_interval.tv_usec) | -		 __put_user(i->it_value.tv_sec, &o->it_value.tv_sec) | -		 __put_user(i->it_value.tv_usec, &o->it_value.tv_usec))); -} - -asmlinkage long sys_ni_posix_timers(void); - -COMPAT_SYSCALL_DEFINE2(getitimer, int, which, -		struct compat_itimerval __user *, it) -{ -	struct itimerval kit; -	int error; - -	if (!IS_ENABLED(CONFIG_POSIX_TIMERS)) -		return sys_ni_posix_timers(); - -	error = do_getitimer(which, &kit); -	if (!error && put_compat_itimerval(it, &kit)) -		error = -EFAULT; -	return error; +	o->it_interval.tv_sec = v32.it_interval.tv_sec; +	o->it_interval.tv_usec = v32.it_interval.tv_usec; +	o->it_value.tv_sec = v32.it_value.tv_sec; +	o->it_value.tv_usec = v32.it_value.tv_usec; +	return 0;  } -COMPAT_SYSCALL_DEFINE3(setitimer, int, which, -		struct compat_itimerval __user *, in, -		struct compat_itimerval __user *, out) +int put_compat_itimerval(struct compat_itimerval __user *o, const struct itimerval *i)  { -	struct itimerval kin, kout; -	int error; - -	if (!IS_ENABLED(CONFIG_POSIX_TIMERS)) -		return sys_ni_posix_timers(); +	struct compat_itimerval v32; -	if (in) { -		if (get_compat_itimerval(&kin, in)) -			return -EFAULT; -	} else -		memset(&kin, 0, sizeof(kin)); - -	error = do_setitimer(which, &kin, out ? &kout : NULL); -	if (error || !out) -		return error; -	if (put_compat_itimerval(out, &kout)) -		return -EFAULT; -	return 0; +	v32.it_interval.tv_sec = i->it_interval.tv_sec; +	v32.it_interval.tv_usec = i->it_interval.tv_usec; +	v32.it_value.tv_sec = i->it_value.tv_sec; +	v32.it_value.tv_usec = i->it_value.tv_usec; +	return copy_to_user(o, &v32, sizeof(struct compat_itimerval)) ? -EFAULT : 0;  }  static compat_clock_t clock_t_to_compat_clock_t(clock_t x) @@ -689,193 +542,6 @@ int put_compat_itimerspec(struct compat_itimerspec __user *dst,  	return 0;  } -COMPAT_SYSCALL_DEFINE3(timer_create, clockid_t, which_clock, -		       struct compat_sigevent __user *, timer_event_spec, -		       timer_t __user *, created_timer_id) -{ -	struct sigevent __user *event = NULL; - -	if (timer_event_spec) { -		struct sigevent kevent; - -		event = compat_alloc_user_space(sizeof(*event)); -		if (get_compat_sigevent(&kevent, timer_event_spec) || -		    copy_to_user(event, &kevent, sizeof(*event))) -			return -EFAULT; -	} - -	return sys_timer_create(which_clock, event, created_timer_id); -} - -COMPAT_SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags, -		       struct compat_itimerspec __user *, new, -		       struct compat_itimerspec __user *, old) -{ -	long err; -	mm_segment_t oldfs; -	struct itimerspec newts, oldts; - -	if (!new) -		return -EINVAL; -	if (get_compat_itimerspec(&newts, new)) -		return -EFAULT; -	oldfs = get_fs(); -	set_fs(KERNEL_DS); -	err = sys_timer_settime(timer_id, flags, -				(struct itimerspec __user *) &newts, -				(struct itimerspec __user *) &oldts); -	set_fs(oldfs); -	if (!err && old && put_compat_itimerspec(old, &oldts)) -		return -EFAULT; -	return err; -} - -COMPAT_SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id, -		       struct compat_itimerspec __user *, setting) -{ -	long err; -	mm_segment_t oldfs; -	struct itimerspec ts; - -	oldfs = get_fs(); -	set_fs(KERNEL_DS); -	err = sys_timer_gettime(timer_id, -				(struct itimerspec __user *) &ts); -	set_fs(oldfs); -	if (!err && put_compat_itimerspec(setting, &ts)) -		return -EFAULT; -	return err; -} - -COMPAT_SYSCALL_DEFINE2(clock_settime, clockid_t, which_clock, -		       struct compat_timespec __user *, tp) -{ -	long err; -	mm_segment_t oldfs; -	struct timespec ts; - -	if (compat_get_timespec(&ts, tp)) -		return -EFAULT; -	oldfs = get_fs(); -	set_fs(KERNEL_DS); -	err = sys_clock_settime(which_clock, -				(struct timespec __user *) &ts); -	set_fs(oldfs); -	return err; -} - -COMPAT_SYSCALL_DEFINE2(clock_gettime, clockid_t, which_clock, -		       struct compat_timespec __user *, tp) -{ -	long err; -	mm_segment_t oldfs; -	struct timespec ts; - -	oldfs = get_fs(); -	set_fs(KERNEL_DS); -	err = sys_clock_gettime(which_clock, -				(struct timespec __user *) &ts); -	set_fs(oldfs); -	if (!err && compat_put_timespec(&ts, tp)) -		return -EFAULT; -	return err; -} - -COMPAT_SYSCALL_DEFINE2(clock_adjtime, clockid_t, which_clock, -		       struct compat_timex __user *, utp) -{ -	struct timex txc; -	mm_segment_t oldfs; -	int err, ret; - -	err = compat_get_timex(&txc, utp); -	if (err) -		return err; - -	oldfs = get_fs(); -	set_fs(KERNEL_DS); -	ret = sys_clock_adjtime(which_clock, (struct timex __user *) &txc); -	set_fs(oldfs); - -	err = compat_put_timex(utp, &txc); -	if (err) -		return err; - -	return ret; -} - -COMPAT_SYSCALL_DEFINE2(clock_getres, clockid_t, which_clock, -		       struct compat_timespec __user *, tp) -{ -	long err; -	mm_segment_t oldfs; -	struct timespec ts; - -	oldfs = get_fs(); -	set_fs(KERNEL_DS); -	err = sys_clock_getres(which_clock, -			       (struct timespec __user *) &ts); -	set_fs(oldfs); -	if (!err && tp && compat_put_timespec(&ts, tp)) -		return -EFAULT; -	return err; -} - -static long compat_clock_nanosleep_restart(struct restart_block *restart) -{ -	long err; -	mm_segment_t oldfs; -	struct timespec tu; -	struct compat_timespec __user *rmtp = restart->nanosleep.compat_rmtp; - -	restart->nanosleep.rmtp = (struct timespec __user *) &tu; -	oldfs = get_fs(); -	set_fs(KERNEL_DS); -	err = clock_nanosleep_restart(restart); -	set_fs(oldfs); - -	if ((err == -ERESTART_RESTARTBLOCK) && rmtp && -	    compat_put_timespec(&tu, rmtp)) -		return -EFAULT; - -	if (err == -ERESTART_RESTARTBLOCK) { -		restart->fn = compat_clock_nanosleep_restart; -		restart->nanosleep.compat_rmtp = rmtp; -	} -	return err; -} - -COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags, -		       struct compat_timespec __user *, rqtp, -		       struct compat_timespec __user *, rmtp) -{ -	long err; -	mm_segment_t oldfs; -	struct timespec in, out; -	struct restart_block *restart; - -	if (compat_get_timespec(&in, rqtp)) -		return -EFAULT; - -	oldfs = get_fs(); -	set_fs(KERNEL_DS); -	err = sys_clock_nanosleep(which_clock, flags, -				  (struct timespec __user *) &in, -				  (struct timespec __user *) &out); -	set_fs(oldfs); - -	if ((err == -ERESTART_RESTARTBLOCK) && rmtp && -	    compat_put_timespec(&out, rmtp)) -		return -EFAULT; - -	if (err == -ERESTART_RESTARTBLOCK) { -		restart = ¤t->restart_block; -		restart->fn = compat_clock_nanosleep_restart; -		restart->nanosleep.compat_rmtp = rmtp; -	} -	return err; -} -  /*   * We currently only need the following fields from the sigevent   * structure: sigev_value, sigev_signo, sig_notify and (sometimes @@ -1035,64 +701,6 @@ COMPAT_SYSCALL_DEFINE4(rt_sigtimedwait, compat_sigset_t __user *, uthese,  	return ret;  } -#ifdef __ARCH_WANT_COMPAT_SYS_TIME - -/* compat_time_t is a 32 bit "long" and needs to get converted. */ - -COMPAT_SYSCALL_DEFINE1(time, compat_time_t __user *, tloc) -{ -	compat_time_t i; -	struct timeval tv; - -	do_gettimeofday(&tv); -	i = tv.tv_sec; - -	if (tloc) { -		if (put_user(i,tloc)) -			return -EFAULT; -	} -	force_successful_syscall_return(); -	return i; -} - -COMPAT_SYSCALL_DEFINE1(stime, compat_time_t __user *, tptr) -{ -	struct timespec tv; -	int err; - -	if (get_user(tv.tv_sec, tptr)) -		return -EFAULT; - -	tv.tv_nsec = 0; - -	err = security_settime(&tv, NULL); -	if (err) -		return err; - -	do_settimeofday(&tv); -	return 0; -} - -#endif /* __ARCH_WANT_COMPAT_SYS_TIME */ - -COMPAT_SYSCALL_DEFINE1(adjtimex, struct compat_timex __user *, utp) -{ -	struct timex txc; -	int err, ret; - -	err = compat_get_timex(&txc, utp); -	if (err) -		return err; - -	ret = do_adjtimex(&txc); - -	err = compat_put_timex(utp, &txc); -	if (err) -		return err; - -	return ret; -} -  #ifdef CONFIG_NUMA  COMPAT_SYSCALL_DEFINE6(move_pages, pid_t, pid, compat_ulong_t, nr_pages,  		       compat_uptr_t __user *, pages32, diff --git a/kernel/signal.c b/kernel/signal.c index 9b28954e058f..35a570f71f07 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -39,6 +39,7 @@  #include <linux/compat.h>  #include <linux/cn_proc.h>  #include <linux/compiler.h> +#include <linux/posix-timers.h>  #define CREATE_TRACE_POINTS  #include <trace/events/signal.h> @@ -637,7 +638,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)  		 * about to disable them again anyway.  		 */  		spin_unlock(&tsk->sighand->siglock); -		do_schedule_next_timer(info); +		posixtimer_rearm(info);  		spin_lock(&tsk->sighand->siglock);  	}  #endif diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index ee2f4202d82a..c991cf212c6d 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c @@ -27,6 +27,9 @@  #include <linux/posix-timers.h>  #include <linux/workqueue.h>  #include <linux/freezer.h> +#include <linux/compat.h> + +#include "posix-timers.h"  #define CREATE_TRACE_POINTS  #include <trace/events/alarmtimer.h> @@ -45,11 +48,13 @@ static struct alarm_base {  	clockid_t		base_clockid;  } alarm_bases[ALARM_NUMTYPE]; +#if defined(CONFIG_POSIX_TIMERS) || defined(CONFIG_RTC_CLASS)  /* freezer information to handle clock_nanosleep triggered wakeups */  static enum alarmtimer_type freezer_alarmtype;  static ktime_t freezer_expires;  static ktime_t freezer_delta;  static DEFINE_SPINLOCK(freezer_delta_lock); +#endif  static struct wakeup_source *ws; @@ -307,38 +312,6 @@ static int alarmtimer_resume(struct device *dev)  }  #endif -static void alarmtimer_freezerset(ktime_t absexp, enum alarmtimer_type type) -{ -	struct alarm_base *base; -	unsigned long flags; -	ktime_t delta; - -	switch(type) { -	case ALARM_REALTIME: -		base = &alarm_bases[ALARM_REALTIME]; -		type = ALARM_REALTIME_FREEZER; -		break; -	case ALARM_BOOTTIME: -		base = &alarm_bases[ALARM_BOOTTIME]; -		type = ALARM_BOOTTIME_FREEZER; -		break; -	default: -		WARN_ONCE(1, "Invalid alarm type: %d\n", type); -		return; -	} - -	delta = ktime_sub(absexp, base->gettime()); - -	spin_lock_irqsave(&freezer_delta_lock, flags); -	if (!freezer_delta || (delta < freezer_delta)) { -		freezer_delta = delta; -		freezer_expires = absexp; -		freezer_alarmtype = type; -	} -	spin_unlock_irqrestore(&freezer_delta_lock, flags); -} - -  /**   * alarm_init - Initialize an alarm structure   * @alarm: ptr to alarm to be initialized @@ -488,6 +461,38 @@ u64 alarm_forward_now(struct alarm *alarm, ktime_t interval)  }  EXPORT_SYMBOL_GPL(alarm_forward_now); +#ifdef CONFIG_POSIX_TIMERS + +static void alarmtimer_freezerset(ktime_t absexp, enum alarmtimer_type type) +{ +	struct alarm_base *base; +	unsigned long flags; +	ktime_t delta; + +	switch(type) { +	case ALARM_REALTIME: +		base = &alarm_bases[ALARM_REALTIME]; +		type = ALARM_REALTIME_FREEZER; +		break; +	case ALARM_BOOTTIME: +		base = &alarm_bases[ALARM_BOOTTIME]; +		type = ALARM_BOOTTIME_FREEZER; +		break; +	default: +		WARN_ONCE(1, "Invalid alarm type: %d\n", type); +		return; +	} + +	delta = ktime_sub(absexp, base->gettime()); + +	spin_lock_irqsave(&freezer_delta_lock, flags); +	if (!freezer_delta || (delta < freezer_delta)) { +		freezer_delta = delta; +		freezer_expires = absexp; +		freezer_alarmtype = type; +	} +	spin_unlock_irqrestore(&freezer_delta_lock, flags); +}  /**   * clock2alarm - helper that converts from clockid to alarmtypes @@ -511,22 +516,26 @@ static enum alarmtimer_type clock2alarm(clockid_t clockid)  static enum alarmtimer_restart alarm_handle_timer(struct alarm *alarm,  							ktime_t now)  { -	unsigned long flags;  	struct k_itimer *ptr = container_of(alarm, struct k_itimer, -						it.alarm.alarmtimer); +					    it.alarm.alarmtimer);  	enum alarmtimer_restart result = ALARMTIMER_NORESTART; +	unsigned long flags; +	int si_private = 0;  	spin_lock_irqsave(&ptr->it_lock, flags); -	if ((ptr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) { -		if (IS_ENABLED(CONFIG_POSIX_TIMERS) && -		    posix_timer_event(ptr, 0) != 0) -			ptr->it_overrun++; -	} -	/* Re-add periodic timers */ -	if (ptr->it.alarm.interval) { -		ptr->it_overrun += alarm_forward(alarm, now, -						ptr->it.alarm.interval); +	ptr->it_active = 0; +	if (ptr->it_interval) +		si_private = ++ptr->it_requeue_pending; + +	if (posix_timer_event(ptr, si_private) && ptr->it_interval) { +		/* +		 * Handle ignored signals and rearm the timer. This will go +		 * away once we handle ignored signals proper. +		 */ +		ptr->it_overrun += alarm_forward_now(alarm, ptr->it_interval); +		++ptr->it_requeue_pending; +		ptr->it_active = 1;  		result = ALARMTIMER_RESTART;  	}  	spin_unlock_irqrestore(&ptr->it_lock, flags); @@ -535,6 +544,72 @@ static enum alarmtimer_restart alarm_handle_timer(struct alarm *alarm,  }  /** + * alarm_timer_rearm - Posix timer callback for rearming timer + * @timr:	Pointer to the posixtimer data struct + */ +static void alarm_timer_rearm(struct k_itimer *timr) +{ +	struct alarm *alarm = &timr->it.alarm.alarmtimer; + +	timr->it_overrun += alarm_forward_now(alarm, timr->it_interval); +	alarm_start(alarm, alarm->node.expires); +} + +/** + * alarm_timer_forward - Posix timer callback for forwarding timer + * @timr:	Pointer to the posixtimer data struct + * @now:	Current time to forward the timer against + */ +static int alarm_timer_forward(struct k_itimer *timr, ktime_t now) +{ +	struct alarm *alarm = &timr->it.alarm.alarmtimer; + +	return (int) alarm_forward(alarm, timr->it_interval, now); +} + +/** + * alarm_timer_remaining - Posix timer callback to retrieve remaining time + * @timr:	Pointer to the posixtimer data struct + * @now:	Current time to calculate against + */ +static ktime_t alarm_timer_remaining(struct k_itimer *timr, ktime_t now) +{ +	struct alarm *alarm = &timr->it.alarm.alarmtimer; + +	return ktime_sub(now, alarm->node.expires); +} + +/** + * alarm_timer_try_to_cancel - Posix timer callback to cancel a timer + * @timr:	Pointer to the posixtimer data struct + */ +static int alarm_timer_try_to_cancel(struct k_itimer *timr) +{ +	return alarm_try_to_cancel(&timr->it.alarm.alarmtimer); +} + +/** + * alarm_timer_arm - Posix timer callback to arm a timer + * @timr:	Pointer to the posixtimer data struct + * @expires:	The new expiry time + * @absolute:	Expiry value is absolute time + * @sigev_none:	Posix timer does not deliver signals + */ +static void alarm_timer_arm(struct k_itimer *timr, ktime_t expires, +			    bool absolute, bool sigev_none) +{ +	struct alarm *alarm = &timr->it.alarm.alarmtimer; +	struct alarm_base *base = &alarm_bases[alarm->type]; + +	if (!absolute) +		expires = ktime_add_safe(expires, base->gettime()); +	if (sigev_none) +		alarm->node.expires = expires; +	else +		alarm_start(&timr->it.alarm.alarmtimer, expires); +} + +/**   * alarm_clock_getres - posix getres interface   * @which_clock: clockid   * @tp: timespec to fill @@ -591,97 +666,6 @@ static int alarm_timer_create(struct k_itimer *new_timer)  }  /** - * alarm_timer_get - posix timer_get interface - * @new_timer: k_itimer pointer - * @cur_setting: itimerspec data to fill - * - * Copies out the current itimerspec data - */ -static void alarm_timer_get(struct k_itimer *timr, -			    struct itimerspec64 *cur_setting) -{ -	ktime_t relative_expiry_time = -		alarm_expires_remaining(&(timr->it.alarm.alarmtimer)); - -	if (ktime_to_ns(relative_expiry_time) > 0) { -		cur_setting->it_value = ktime_to_timespec64(relative_expiry_time); -	} else { -		cur_setting->it_value.tv_sec = 0; -		cur_setting->it_value.tv_nsec = 0; -	} - -	cur_setting->it_interval = ktime_to_timespec64(timr->it.alarm.interval); -} - -/** - * alarm_timer_del - posix timer_del interface - * @timr: k_itimer pointer to be deleted - * - * Cancels any programmed alarms for the given timer. - */ -static int alarm_timer_del(struct k_itimer *timr) -{ -	if (!rtcdev) -		return -ENOTSUPP; - -	if (alarm_try_to_cancel(&timr->it.alarm.alarmtimer) < 0) -		return TIMER_RETRY; - -	return 0; -} - -/** - * alarm_timer_set - posix timer_set interface - * @timr: k_itimer pointer to be deleted - * @flags: timer flags - * @new_setting: itimerspec to be used - * @old_setting: itimerspec being replaced - * - * Sets the timer to new_setting, and starts the timer. - */ -static int alarm_timer_set(struct k_itimer *timr, int flags, -			   struct itimerspec64 *new_setting, -			   struct itimerspec64 *old_setting) -{ -	ktime_t exp; - -	if (!rtcdev) -		return -ENOTSUPP; - -	if (flags & ~TIMER_ABSTIME) -		return -EINVAL; - -	if (old_setting) -		alarm_timer_get(timr, old_setting); - -	/* If the timer was already set, cancel it */ -	if (alarm_try_to_cancel(&timr->it.alarm.alarmtimer) < 0) -		return TIMER_RETRY; - -	/* start the timer */ -	timr->it.alarm.interval = timespec64_to_ktime(new_setting->it_interval); - -	/* -	 * Rate limit to the tick as a hot fix to prevent DOS. Will be -	 * mopped up later. -	 */ -	if (timr->it.alarm.interval < TICK_NSEC) -		timr->it.alarm.interval = TICK_NSEC; - -	exp = timespec64_to_ktime(new_setting->it_value); -	/* Convert (if necessary) to absolute time */ -	if (flags != TIMER_ABSTIME) { -		ktime_t now; - -		now = alarm_bases[timr->it.alarm.alarmtimer.type].gettime(); -		exp = ktime_add_safe(now, exp); -	} - -	alarm_start(&timr->it.alarm.alarmtimer, exp); -	return 0; -} - -/**   * alarmtimer_nsleep_wakeup - Wakeup function for alarm_timer_nsleep   * @alarm: ptr to alarm that fired   * @@ -705,8 +689,10 @@ static enum alarmtimer_restart alarmtimer_nsleep_wakeup(struct alarm *alarm,   *   * Sets the alarm timer and sleeps until it is fired or interrupted.   */ -static int alarmtimer_do_nsleep(struct alarm *alarm, ktime_t absexp) +static int alarmtimer_do_nsleep(struct alarm *alarm, ktime_t absexp, +				enum alarmtimer_type type)  { +	struct restart_block *restart;  	alarm->data = (void *)current;  	do {  		set_current_state(TASK_INTERRUPTIBLE); @@ -719,36 +705,25 @@ static int alarmtimer_do_nsleep(struct alarm *alarm, ktime_t absexp)  	__set_current_state(TASK_RUNNING); -	return (alarm->data == NULL); -} - - -/** - * update_rmtp - Update remaining timespec value - * @exp: expiration time - * @type: timer type - * @rmtp: user pointer to remaining timepsec value - * - * Helper function that fills in rmtp value with time between - * now and the exp value - */ -static int update_rmtp(ktime_t exp, enum  alarmtimer_type type, -			struct timespec __user *rmtp) -{ -	struct timespec rmt; -	ktime_t rem; - -	rem = ktime_sub(exp, alarm_bases[type].gettime()); - -	if (rem <= 0) +	if (!alarm->data)  		return 0; -	rmt = ktime_to_timespec(rem); -	if (copy_to_user(rmtp, &rmt, sizeof(*rmtp))) -		return -EFAULT; +	if (freezing(current)) +		alarmtimer_freezerset(absexp, type); +	restart = ¤t->restart_block; +	if (restart->nanosleep.type != TT_NONE) { +		struct timespec rmt; +		ktime_t rem; + +		rem = ktime_sub(absexp, alarm_bases[type].gettime()); -	return 1; +		if (rem <= 0) +			return 0; +		rmt = ktime_to_timespec(rem); +		return nanosleep_copyout(restart, &rmt); +	} +	return -ERESTART_RESTARTBLOCK;  }  /** @@ -760,32 +735,12 @@ static int update_rmtp(ktime_t exp, enum  alarmtimer_type type,  static long __sched alarm_timer_nsleep_restart(struct restart_block *restart)  {  	enum  alarmtimer_type type = restart->nanosleep.clockid; -	ktime_t exp; -	struct timespec __user  *rmtp; +	ktime_t exp = restart->nanosleep.expires;  	struct alarm alarm; -	int ret = 0; -	exp = restart->nanosleep.expires;  	alarm_init(&alarm, type, alarmtimer_nsleep_wakeup); -	if (alarmtimer_do_nsleep(&alarm, exp)) -		goto out; - -	if (freezing(current)) -		alarmtimer_freezerset(exp, type); - -	rmtp = restart->nanosleep.rmtp; -	if (rmtp) { -		ret = update_rmtp(exp, type, rmtp); -		if (ret <= 0) -			goto out; -	} - - -	/* The other values in restart are already filled in */ -	ret = -ERESTART_RESTARTBLOCK; -out: -	return ret; +	return alarmtimer_do_nsleep(&alarm, exp, type);  }  /** @@ -798,11 +753,10 @@ out:   * Handles clock_nanosleep calls against _ALARM clockids   */  static int alarm_timer_nsleep(const clockid_t which_clock, int flags, -			      struct timespec64 *tsreq, -			      struct timespec __user *rmtp) +			      const struct timespec64 *tsreq)  {  	enum  alarmtimer_type type = clock2alarm(which_clock); -	struct restart_block *restart; +	struct restart_block *restart = ¤t->restart_block;  	struct alarm alarm;  	ktime_t exp;  	int ret = 0; @@ -825,35 +779,36 @@ static int alarm_timer_nsleep(const clockid_t which_clock, int flags,  		exp = ktime_add(now, exp);  	} -	if (alarmtimer_do_nsleep(&alarm, exp)) -		goto out; - -	if (freezing(current)) -		alarmtimer_freezerset(exp, type); +	ret = alarmtimer_do_nsleep(&alarm, exp, type); +	if (ret != -ERESTART_RESTARTBLOCK) +		return ret;  	/* abs timers don't set remaining time or restart */ -	if (flags == TIMER_ABSTIME) { -		ret = -ERESTARTNOHAND; -		goto out; -	} +	if (flags == TIMER_ABSTIME) +		return -ERESTARTNOHAND; -	if (rmtp) { -		ret = update_rmtp(exp, type, rmtp); -		if (ret <= 0) -			goto out; -	} - -	restart = ¤t->restart_block;  	restart->fn = alarm_timer_nsleep_restart;  	restart->nanosleep.clockid = type;  	restart->nanosleep.expires = exp; -	restart->nanosleep.rmtp = rmtp; -	ret = -ERESTART_RESTARTBLOCK; - -out:  	return ret;  } +const struct k_clock alarm_clock = { +	.clock_getres		= alarm_clock_getres, +	.clock_get		= alarm_clock_get, +	.timer_create		= alarm_timer_create, +	.timer_set		= common_timer_set, +	.timer_del		= common_timer_del, +	.timer_get		= common_timer_get, +	.timer_arm		= alarm_timer_arm, +	.timer_rearm		= alarm_timer_rearm, +	.timer_forward		= alarm_timer_forward, +	.timer_remaining	= alarm_timer_remaining, +	.timer_try_to_cancel	= alarm_timer_try_to_cancel, +	.nsleep			= alarm_timer_nsleep, +}; +#endif /* CONFIG_POSIX_TIMERS */ +  /* Suspend hook structures */  static const struct dev_pm_ops alarmtimer_pm_ops = { @@ -879,23 +834,9 @@ static int __init alarmtimer_init(void)  	struct platform_device *pdev;  	int error = 0;  	int i; -	struct k_clock alarm_clock = { -		.clock_getres	= alarm_clock_getres, -		.clock_get	= alarm_clock_get, -		.timer_create	= alarm_timer_create, -		.timer_set	= alarm_timer_set, -		.timer_del	= alarm_timer_del, -		.timer_get	= alarm_timer_get, -		.nsleep		= alarm_timer_nsleep, -	};  	alarmtimer_rtc_timer_init(); -	if (IS_ENABLED(CONFIG_POSIX_TIMERS)) { -		posix_timers_register_clock(CLOCK_REALTIME_ALARM, &alarm_clock); -		posix_timers_register_clock(CLOCK_BOOTTIME_ALARM, &alarm_clock); -	} -  	/* Initialize alarm bases */  	alarm_bases[ALARM_REALTIME].base_clockid = CLOCK_REALTIME;  	alarm_bases[ALARM_REALTIME].gettime = &ktime_get_real; diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index ac053bb5296e..81da124f1115 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c @@ -51,6 +51,7 @@  #include <linux/sched/debug.h>  #include <linux/timer.h>  #include <linux/freezer.h> +#include <linux/compat.h>  #include <linux/uaccess.h> @@ -1439,8 +1440,29 @@ void hrtimer_init_sleeper(struct hrtimer_sleeper *sl, struct task_struct *task)  }  EXPORT_SYMBOL_GPL(hrtimer_init_sleeper); +int nanosleep_copyout(struct restart_block *restart, struct timespec *ts) +{ +	switch(restart->nanosleep.type) { +#ifdef CONFIG_COMPAT +	case TT_COMPAT: +		if (compat_put_timespec(ts, restart->nanosleep.compat_rmtp)) +			return -EFAULT; +		break; +#endif +	case TT_NATIVE: +		if (copy_to_user(restart->nanosleep.rmtp, ts, sizeof(struct timespec))) +			return -EFAULT; +		break; +	default: +		BUG(); +	} +	return -ERESTART_RESTARTBLOCK; +} +  static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mode)  { +	struct restart_block *restart; +  	hrtimer_init_sleeper(t, current);  	do { @@ -1457,53 +1479,38 @@ static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mod  	__set_current_state(TASK_RUNNING); -	return t->task == NULL; -} - -static int update_rmtp(struct hrtimer *timer, struct timespec __user *rmtp) -{ -	struct timespec rmt; -	ktime_t rem; - -	rem = hrtimer_expires_remaining(timer); -	if (rem <= 0) +	if (!t->task)  		return 0; -	rmt = ktime_to_timespec(rem); -	if (copy_to_user(rmtp, &rmt, sizeof(*rmtp))) -		return -EFAULT; +	restart = ¤t->restart_block; +	if (restart->nanosleep.type != TT_NONE) { +		ktime_t rem = hrtimer_expires_remaining(&t->timer); +		struct timespec rmt; -	return 1; +		if (rem <= 0) +			return 0; +		rmt = ktime_to_timespec(rem); + +		return nanosleep_copyout(restart, &rmt); +	} +	return -ERESTART_RESTARTBLOCK;  } -long __sched hrtimer_nanosleep_restart(struct restart_block *restart) +static long __sched hrtimer_nanosleep_restart(struct restart_block *restart)  {  	struct hrtimer_sleeper t; -	struct timespec __user  *rmtp; -	int ret = 0; +	int ret;  	hrtimer_init_on_stack(&t.timer, restart->nanosleep.clockid,  				HRTIMER_MODE_ABS);  	hrtimer_set_expires_tv64(&t.timer, restart->nanosleep.expires); -	if (do_nanosleep(&t, HRTIMER_MODE_ABS)) -		goto out; - -	rmtp = restart->nanosleep.rmtp; -	if (rmtp) { -		ret = update_rmtp(&t.timer, rmtp); -		if (ret <= 0) -			goto out; -	} - -	/* The other values in restart are already filled in */ -	ret = -ERESTART_RESTARTBLOCK; -out: +	ret = do_nanosleep(&t, HRTIMER_MODE_ABS);  	destroy_hrtimer_on_stack(&t.timer);  	return ret;  } -long hrtimer_nanosleep(struct timespec64 *rqtp, struct timespec __user *rmtp, +long hrtimer_nanosleep(const struct timespec64 *rqtp,  		       const enum hrtimer_mode mode, const clockid_t clockid)  {  	struct restart_block *restart; @@ -1517,7 +1524,8 @@ long hrtimer_nanosleep(struct timespec64 *rqtp, struct timespec __user *rmtp,  	hrtimer_init_on_stack(&t.timer, clockid, mode);  	hrtimer_set_expires_range_ns(&t.timer, timespec64_to_ktime(*rqtp), slack); -	if (do_nanosleep(&t, mode)) +	ret = do_nanosleep(&t, mode); +	if (ret != -ERESTART_RESTARTBLOCK)  		goto out;  	/* Absolute timers do not update the rmtp value and restart: */ @@ -1526,19 +1534,10 @@ long hrtimer_nanosleep(struct timespec64 *rqtp, struct timespec __user *rmtp,  		goto out;  	} -	if (rmtp) { -		ret = update_rmtp(&t.timer, rmtp); -		if (ret <= 0) -			goto out; -	} -  	restart = ¤t->restart_block;  	restart->fn = hrtimer_nanosleep_restart;  	restart->nanosleep.clockid = t.timer.base->clockid; -	restart->nanosleep.rmtp = rmtp;  	restart->nanosleep.expires = hrtimer_get_expires_tv64(&t.timer); - -	ret = -ERESTART_RESTARTBLOCK;  out:  	destroy_hrtimer_on_stack(&t.timer);  	return ret; @@ -1557,8 +1556,31 @@ SYSCALL_DEFINE2(nanosleep, struct timespec __user *, rqtp,  	if (!timespec64_valid(&tu64))  		return -EINVAL; -	return hrtimer_nanosleep(&tu64, rmtp, HRTIMER_MODE_REL, CLOCK_MONOTONIC); +	current->restart_block.nanosleep.type = rmtp ? TT_NATIVE : TT_NONE; +	current->restart_block.nanosleep.rmtp = rmtp; +	return hrtimer_nanosleep(&tu64, HRTIMER_MODE_REL, CLOCK_MONOTONIC); +} + +#ifdef CONFIG_COMPAT + +COMPAT_SYSCALL_DEFINE2(nanosleep, struct compat_timespec __user *, rqtp, +		       struct compat_timespec __user *, rmtp) +{ +	struct timespec64 tu64; +	struct timespec tu; + +	if (compat_get_timespec(&tu, rqtp)) +		return -EFAULT; + +	tu64 = timespec_to_timespec64(tu); +	if (!timespec64_valid(&tu64)) +		return -EINVAL; + +	current->restart_block.nanosleep.type = rmtp ? TT_COMPAT : TT_NONE; +	current->restart_block.nanosleep.compat_rmtp = rmtp; +	return hrtimer_nanosleep(&tu64, HRTIMER_MODE_REL, CLOCK_MONOTONIC);  } +#endif  /*   * Functions related to boot-time initialization: diff --git a/kernel/time/itimer.c b/kernel/time/itimer.c index 087d6a1279b8..2ef98a02376a 100644 --- a/kernel/time/itimer.c +++ b/kernel/time/itimer.c @@ -15,6 +15,7 @@  #include <linux/posix-timers.h>  #include <linux/hrtimer.h>  #include <trace/events/timer.h> +#include <linux/compat.h>  #include <linux/uaccess.h> @@ -116,6 +117,19 @@ SYSCALL_DEFINE2(getitimer, int, which, struct itimerval __user *, value)  	return error;  } +#ifdef CONFIG_COMPAT +COMPAT_SYSCALL_DEFINE2(getitimer, int, which, +		       struct compat_itimerval __user *, it) +{ +	struct itimerval kit; +	int error = do_getitimer(which, &kit); + +	if (!error && put_compat_itimerval(it, &kit)) +		error = -EFAULT; +	return error; +} +#endif +  /*   * The timer is automagically restarted, when interval != 0 @@ -138,8 +152,12 @@ static void set_cpu_itimer(struct task_struct *tsk, unsigned int clock_id,  	u64 oval, nval, ointerval, ninterval;  	struct cpu_itimer *it = &tsk->signal->it[clock_id]; -	nval = timeval_to_ns(&value->it_value); -	ninterval = timeval_to_ns(&value->it_interval); +	/* +	 * Use the to_ktime conversion because that clamps the maximum +	 * value to KTIME_MAX and avoid multiplication overflows. +	 */ +	nval = ktime_to_ns(timeval_to_ktime(value->it_value)); +	ninterval = ktime_to_ns(timeval_to_ktime(value->it_interval));  	spin_lock_irq(&tsk->sighand->siglock); @@ -294,3 +312,27 @@ SYSCALL_DEFINE3(setitimer, int, which, struct itimerval __user *, value,  		return -EFAULT;  	return 0;  } + +#ifdef CONFIG_COMPAT +COMPAT_SYSCALL_DEFINE3(setitimer, int, which, +		       struct compat_itimerval __user *, in, +		       struct compat_itimerval __user *, out) +{ +	struct itimerval kin, kout; +	int error; + +	if (in) { +		if (get_compat_itimerval(&kin, in)) +			return -EFAULT; +	} else { +		memset(&kin, 0, sizeof(kin)); +	} + +	error = do_setitimer(which, &kin, out ? &kout : NULL); +	if (error || !out) +		return error; +	if (put_compat_itimerval(out, &kout)) +		return -EFAULT; +	return 0; +} +#endif diff --git a/kernel/time/posix-clock.c b/kernel/time/posix-clock.c index 31d588d37a17..17cdc554c9fe 100644 --- a/kernel/time/posix-clock.c +++ b/kernel/time/posix-clock.c @@ -25,6 +25,8 @@  #include <linux/syscalls.h>  #include <linux/uaccess.h> +#include "posix-timers.h" +  static void delete_clock(struct kref *kref);  /* @@ -82,38 +84,6 @@ static unsigned int posix_clock_poll(struct file *fp, poll_table *wait)  	return result;  } -static int posix_clock_fasync(int fd, struct file *fp, int on) -{ -	struct posix_clock *clk = get_posix_clock(fp); -	int err = 0; - -	if (!clk) -		return -ENODEV; - -	if (clk->ops.fasync) -		err = clk->ops.fasync(clk, fd, fp, on); - -	put_posix_clock(clk); - -	return err; -} - -static int posix_clock_mmap(struct file *fp, struct vm_area_struct *vma) -{ -	struct posix_clock *clk = get_posix_clock(fp); -	int err = -ENODEV; - -	if (!clk) -		return -ENODEV; - -	if (clk->ops.mmap) -		err = clk->ops.mmap(clk, vma); - -	put_posix_clock(clk); - -	return err; -} -  static long posix_clock_ioctl(struct file *fp,  			      unsigned int cmd, unsigned long arg)  { @@ -199,8 +169,6 @@ static const struct file_operations posix_clock_file_operations = {  	.unlocked_ioctl	= posix_clock_ioctl,  	.open		= posix_clock_open,  	.release	= posix_clock_release, -	.fasync		= posix_clock_fasync, -	.mmap		= posix_clock_mmap,  #ifdef CONFIG_COMPAT  	.compat_ioctl	= posix_clock_compat_ioctl,  #endif @@ -359,88 +327,9 @@ out:  	return err;  } -static int pc_timer_create(struct k_itimer *kit) -{ -	clockid_t id = kit->it_clock; -	struct posix_clock_desc cd; -	int err; - -	err = get_clock_desc(id, &cd); -	if (err) -		return err; - -	if (cd.clk->ops.timer_create) -		err = cd.clk->ops.timer_create(cd.clk, kit); -	else -		err = -EOPNOTSUPP; - -	put_clock_desc(&cd); - -	return err; -} - -static int pc_timer_delete(struct k_itimer *kit) -{ -	clockid_t id = kit->it_clock; -	struct posix_clock_desc cd; -	int err; - -	err = get_clock_desc(id, &cd); -	if (err) -		return err; - -	if (cd.clk->ops.timer_delete) -		err = cd.clk->ops.timer_delete(cd.clk, kit); -	else -		err = -EOPNOTSUPP; - -	put_clock_desc(&cd); - -	return err; -} - -static void pc_timer_gettime(struct k_itimer *kit, struct itimerspec64 *ts) -{ -	clockid_t id = kit->it_clock; -	struct posix_clock_desc cd; - -	if (get_clock_desc(id, &cd)) -		return; - -	if (cd.clk->ops.timer_gettime) -		cd.clk->ops.timer_gettime(cd.clk, kit, ts); - -	put_clock_desc(&cd); -} - -static int pc_timer_settime(struct k_itimer *kit, int flags, -			    struct itimerspec64 *ts, struct itimerspec64 *old) -{ -	clockid_t id = kit->it_clock; -	struct posix_clock_desc cd; -	int err; - -	err = get_clock_desc(id, &cd); -	if (err) -		return err; - -	if (cd.clk->ops.timer_settime) -		err = cd.clk->ops.timer_settime(cd.clk, kit, flags, ts, old); -	else -		err = -EOPNOTSUPP; - -	put_clock_desc(&cd); - -	return err; -} - -struct k_clock clock_posix_dynamic = { +const struct k_clock clock_posix_dynamic = {  	.clock_getres	= pc_clock_getres,  	.clock_set	= pc_clock_settime,  	.clock_get	= pc_clock_gettime,  	.clock_adj	= pc_clock_adjtime, -	.timer_create	= pc_timer_create, -	.timer_set	= pc_timer_settime, -	.timer_del	= pc_timer_delete, -	.timer_get	= pc_timer_gettime,  }; diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c index d2a1e6dd0291..60cb24ac9ebc 100644 --- a/kernel/time/posix-cpu-timers.c +++ b/kernel/time/posix-cpu-timers.c @@ -12,6 +12,11 @@  #include <trace/events/timer.h>  #include <linux/tick.h>  #include <linux/workqueue.h> +#include <linux/compat.h> + +#include "posix-timers.h" + +static void posix_cpu_timer_rearm(struct k_itimer *timer);  /*   * Called after updating RLIMIT_CPU to run cpu timer and update @@ -322,6 +327,8 @@ static int posix_cpu_timer_create(struct k_itimer *new_timer)  	if (CPUCLOCK_WHICH(new_timer->it_clock) >= CPUCLOCK_MAX)  		return -EINVAL; +	new_timer->kclock = &clock_posix_cpu; +  	INIT_LIST_HEAD(&new_timer->it.cpu.entry);  	rcu_read_lock(); @@ -524,7 +531,8 @@ static void cpu_timer_fire(struct k_itimer *timer)  		 * reload the timer.  But we need to keep it  		 * ticking in case the signal is deliverable next time.  		 */ -		posix_cpu_timer_schedule(timer); +		posix_cpu_timer_rearm(timer); +		++timer->it_requeue_pending;  	}  } @@ -572,7 +580,11 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,  	WARN_ON_ONCE(p == NULL); -	new_expires = timespec64_to_ns(&new->it_value); +	/* +	 * Use the to_ktime conversion because that clamps the maximum +	 * value to KTIME_MAX and avoid multiplication overflows. +	 */ +	new_expires = ktime_to_ns(timespec64_to_ktime(new->it_value));  	/*  	 * Protect against sighand release/switch in exit/exec and p->cpu_timers @@ -712,10 +724,8 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec64 *itp  	 */  	itp->it_interval = ns_to_timespec64(timer->it.cpu.incr); -	if (timer->it.cpu.expires == 0) {	/* Timer not armed at all.  */ -		itp->it_value.tv_sec = itp->it_value.tv_nsec = 0; +	if (!timer->it.cpu.expires)  		return; -	}  	/*  	 * Sample the clock to take the difference with the expiry time. @@ -739,7 +749,6 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec64 *itp  			 * Call the timer disarmed, nothing else to do.  			 */  			timer->it.cpu.expires = 0; -			itp->it_value = ns_to_timespec64(timer->it.cpu.expires);  			return;  		} else {  			cpu_timer_sample_group(timer->it_clock, p, &now); @@ -976,10 +985,10 @@ static void check_process_timers(struct task_struct *tsk,  }  /* - * This is called from the signal code (via do_schedule_next_timer) + * This is called from the signal code (via posixtimer_rearm)   * when the last timer signal was delivered and we have to reload the timer.   */ -void posix_cpu_timer_schedule(struct k_itimer *timer) +static void posix_cpu_timer_rearm(struct k_itimer *timer)  {  	struct sighand_struct *sighand;  	unsigned long flags; @@ -995,12 +1004,12 @@ void posix_cpu_timer_schedule(struct k_itimer *timer)  		cpu_clock_sample(timer->it_clock, p, &now);  		bump_cpu_timer(timer, now);  		if (unlikely(p->exit_state)) -			goto out; +			return;  		/* Protect timer list r/w in arm_timer() */  		sighand = lock_task_sighand(p, &flags);  		if (!sighand) -			goto out; +			return;  	} else {  		/*  		 * Protect arm_timer() and timer sampling in case of call to @@ -1013,11 +1022,10 @@ void posix_cpu_timer_schedule(struct k_itimer *timer)  			 * We can't even collect a sample any more.  			 */  			timer->it.cpu.expires = 0; -			goto out; +			return;  		} else if (unlikely(p->exit_state) && thread_group_empty(p)) { -			unlock_task_sighand(p, &flags); -			/* Optimizations: if the process is dying, no need to rearm */ -			goto out; +			/* If the process is dying, no need to rearm */ +			goto unlock;  		}  		cpu_timer_sample_group(timer->it_clock, p, &now);  		bump_cpu_timer(timer, now); @@ -1029,12 +1037,8 @@ void posix_cpu_timer_schedule(struct k_itimer *timer)  	 */  	WARN_ON_ONCE(!irqs_disabled());  	arm_timer(timer); +unlock:  	unlock_task_sighand(p, &flags); - -out: -	timer->it_overrun_last = timer->it_overrun; -	timer->it_overrun = -1; -	++timer->it_requeue_pending;  }  /** @@ -1227,9 +1231,11 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx,  }  static int do_cpu_nanosleep(const clockid_t which_clock, int flags, -			    struct timespec64 *rqtp, struct itimerspec64 *it) +			    const struct timespec64 *rqtp)  { +	struct itimerspec64 it;  	struct k_itimer timer; +	u64 expires;  	int error;  	/* @@ -1243,12 +1249,13 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,  	timer.it_process = current;  	if (!error) {  		static struct itimerspec64 zero_it; +		struct restart_block *restart; -		memset(it, 0, sizeof *it); -		it->it_value = *rqtp; +		memset(&it, 0, sizeof(it)); +		it.it_value = *rqtp;  		spin_lock_irq(&timer.it_lock); -		error = posix_cpu_timer_set(&timer, flags, it, NULL); +		error = posix_cpu_timer_set(&timer, flags, &it, NULL);  		if (error) {  			spin_unlock_irq(&timer.it_lock);  			return error; @@ -1277,8 +1284,8 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,  		/*  		 * We were interrupted by a signal.  		 */ -		*rqtp = ns_to_timespec64(timer.it.cpu.expires); -		error = posix_cpu_timer_set(&timer, 0, &zero_it, it); +		expires = timer.it.cpu.expires; +		error = posix_cpu_timer_set(&timer, 0, &zero_it, &it);  		if (!error) {  			/*  			 * Timer is now unarmed, deletion can not fail. @@ -1298,7 +1305,7 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,  			spin_unlock_irq(&timer.it_lock);  		} -		if ((it->it_value.tv_sec | it->it_value.tv_nsec) == 0) { +		if ((it.it_value.tv_sec | it.it_value.tv_nsec) == 0) {  			/*  			 * It actually did fire already.  			 */ @@ -1306,6 +1313,17 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,  		}  		error = -ERESTART_RESTARTBLOCK; +		/* +		 * Report back to the user the time still remaining. +		 */ +		restart = ¤t->restart_block; +		restart->nanosleep.expires = expires; +		if (restart->nanosleep.type != TT_NONE) { +			struct timespec ts; + +			ts = timespec64_to_timespec(it.it_value); +			error = nanosleep_copyout(restart, &ts); +		}  	}  	return error; @@ -1314,11 +1332,9 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,  static long posix_cpu_nsleep_restart(struct restart_block *restart_block);  static int posix_cpu_nsleep(const clockid_t which_clock, int flags, -			    struct timespec64 *rqtp, struct timespec __user *rmtp) +			    const struct timespec64 *rqtp)  {  	struct restart_block *restart_block = ¤t->restart_block; -	struct itimerspec64 it; -	struct timespec ts;  	int error;  	/* @@ -1329,23 +1345,15 @@ static int posix_cpu_nsleep(const clockid_t which_clock, int flags,  	     CPUCLOCK_PID(which_clock) == task_pid_vnr(current)))  		return -EINVAL; -	error = do_cpu_nanosleep(which_clock, flags, rqtp, &it); +	error = do_cpu_nanosleep(which_clock, flags, rqtp);  	if (error == -ERESTART_RESTARTBLOCK) {  		if (flags & TIMER_ABSTIME)  			return -ERESTARTNOHAND; -		/* -		 * Report back to the user the time still remaining. -		 */ -		ts = timespec64_to_timespec(it.it_value); -		if (rmtp && copy_to_user(rmtp, &ts, sizeof(*rmtp))) -			return -EFAULT;  		restart_block->fn = posix_cpu_nsleep_restart;  		restart_block->nanosleep.clockid = which_clock; -		restart_block->nanosleep.rmtp = rmtp; -		restart_block->nanosleep.expires = timespec64_to_ns(rqtp);  	}  	return error;  } @@ -1353,28 +1361,11 @@ static int posix_cpu_nsleep(const clockid_t which_clock, int flags,  static long posix_cpu_nsleep_restart(struct restart_block *restart_block)  {  	clockid_t which_clock = restart_block->nanosleep.clockid; -	struct itimerspec64 it;  	struct timespec64 t; -	struct timespec tmp; -	int error;  	t = ns_to_timespec64(restart_block->nanosleep.expires); -	error = do_cpu_nanosleep(which_clock, TIMER_ABSTIME, &t, &it); - -	if (error == -ERESTART_RESTARTBLOCK) { -		struct timespec __user *rmtp = restart_block->nanosleep.rmtp; -		/* -		 * Report back to the user the time still remaining. -		 */ -		 tmp = timespec64_to_timespec(it.it_value); -		if (rmtp && copy_to_user(rmtp, &tmp, sizeof(*rmtp))) -			return -EFAULT; - -		restart_block->nanosleep.expires = timespec64_to_ns(&t); -	} -	return error; - +	return do_cpu_nanosleep(which_clock, TIMER_ABSTIME, &t);  }  #define PROCESS_CLOCK	MAKE_PROCESS_CPUCLOCK(0, CPUCLOCK_SCHED) @@ -1396,14 +1387,9 @@ static int process_cpu_timer_create(struct k_itimer *timer)  	return posix_cpu_timer_create(timer);  }  static int process_cpu_nsleep(const clockid_t which_clock, int flags, -			      struct timespec64 *rqtp, -			      struct timespec __user *rmtp) -{ -	return posix_cpu_nsleep(PROCESS_CLOCK, flags, rqtp, rmtp); -} -static long process_cpu_nsleep_restart(struct restart_block *restart_block) +			      const struct timespec64 *rqtp)  { -	return -EINVAL; +	return posix_cpu_nsleep(PROCESS_CLOCK, flags, rqtp);  }  static int thread_cpu_clock_getres(const clockid_t which_clock,  				   struct timespec64 *tp) @@ -1421,36 +1407,27 @@ static int thread_cpu_timer_create(struct k_itimer *timer)  	return posix_cpu_timer_create(timer);  } -struct k_clock clock_posix_cpu = { +const struct k_clock clock_posix_cpu = {  	.clock_getres	= posix_cpu_clock_getres,  	.clock_set	= posix_cpu_clock_set,  	.clock_get	= posix_cpu_clock_get,  	.timer_create	= posix_cpu_timer_create,  	.nsleep		= posix_cpu_nsleep, -	.nsleep_restart	= posix_cpu_nsleep_restart,  	.timer_set	= posix_cpu_timer_set,  	.timer_del	= posix_cpu_timer_del,  	.timer_get	= posix_cpu_timer_get, +	.timer_rearm	= posix_cpu_timer_rearm,  }; -static __init int init_posix_cpu_timers(void) -{ -	struct k_clock process = { -		.clock_getres	= process_cpu_clock_getres, -		.clock_get	= process_cpu_clock_get, -		.timer_create	= process_cpu_timer_create, -		.nsleep		= process_cpu_nsleep, -		.nsleep_restart	= process_cpu_nsleep_restart, -	}; -	struct k_clock thread = { -		.clock_getres	= thread_cpu_clock_getres, -		.clock_get	= thread_cpu_clock_get, -		.timer_create	= thread_cpu_timer_create, -	}; - -	posix_timers_register_clock(CLOCK_PROCESS_CPUTIME_ID, &process); -	posix_timers_register_clock(CLOCK_THREAD_CPUTIME_ID, &thread); +const struct k_clock clock_process = { +	.clock_getres	= process_cpu_clock_getres, +	.clock_get	= process_cpu_clock_get, +	.timer_create	= process_cpu_timer_create, +	.nsleep		= process_cpu_nsleep, +}; -	return 0; -} -__initcall(init_posix_cpu_timers); +const struct k_clock clock_thread = { +	.clock_getres	= thread_cpu_clock_getres, +	.clock_get	= thread_cpu_clock_get, +	.timer_create	= thread_cpu_timer_create, +}; diff --git a/kernel/time/posix-stubs.c b/kernel/time/posix-stubs.c index c0cd53eb018a..38f3b20efa29 100644 --- a/kernel/time/posix-stubs.c +++ b/kernel/time/posix-stubs.c @@ -17,6 +17,7 @@  #include <linux/ktime.h>  #include <linux/timekeeping.h>  #include <linux/posix-timers.h> +#include <linux/compat.h>  asmlinkage long sys_ni_posix_timers(void)  { @@ -27,6 +28,7 @@ asmlinkage long sys_ni_posix_timers(void)  }  #define SYS_NI(name)  SYSCALL_ALIAS(sys_##name, sys_ni_posix_timers) +#define COMPAT_SYS_NI(name)  SYSCALL_ALIAS(compat_sys_##name, sys_ni_posix_timers)  SYS_NI(timer_create);  SYS_NI(timer_gettime); @@ -39,6 +41,12 @@ SYS_NI(setitimer);  #ifdef __ARCH_WANT_SYS_ALARM  SYS_NI(alarm);  #endif +COMPAT_SYS_NI(timer_create); +COMPAT_SYS_NI(clock_adjtime); +COMPAT_SYS_NI(timer_settime); +COMPAT_SYS_NI(timer_gettime); +COMPAT_SYS_NI(getitimer); +COMPAT_SYS_NI(setitimer);  /*   * We preserve minimal support for CLOCK_REALTIME and CLOCK_MONOTONIC @@ -110,22 +118,106 @@ SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags,  	case CLOCK_REALTIME:  	case CLOCK_MONOTONIC:  	case CLOCK_BOOTTIME: -		if (copy_from_user(&t, rqtp, sizeof (struct timespec))) -			return -EFAULT; -		t64 = timespec_to_timespec64(t); -		if (!timespec64_valid(&t64)) -			return -EINVAL; -		return hrtimer_nanosleep(&t64, rmtp, flags & TIMER_ABSTIME ? -					 HRTIMER_MODE_ABS : HRTIMER_MODE_REL, -					 which_clock); +		break;  	default:  		return -EINVAL;  	} + +	if (copy_from_user(&t, rqtp, sizeof (struct timespec))) +		return -EFAULT; +	t64 = timespec_to_timespec64(t); +	if (!timespec64_valid(&t64)) +		return -EINVAL; +	if (flags & TIMER_ABSTIME) +		rmtp = NULL; +	current->restart_block.nanosleep.type = rmtp ? TT_NATIVE : TT_NONE; +	current->restart_block.nanosleep.rmtp = rmtp; +	return hrtimer_nanosleep(&t64, flags & TIMER_ABSTIME ? +				 HRTIMER_MODE_ABS : HRTIMER_MODE_REL, +				 which_clock);  }  #ifdef CONFIG_COMPAT -long clock_nanosleep_restart(struct restart_block *restart_block) +COMPAT_SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock, +		       struct compat_timespec __user *, tp) +{ +	struct timespec64 new_tp64; +	struct timespec new_tp; + +	if (which_clock != CLOCK_REALTIME) +		return -EINVAL; +	if (compat_get_timespec(&new_tp, tp)) +		return -EFAULT; + +	new_tp64 = timespec_to_timespec64(new_tp); +	return do_sys_settimeofday64(&new_tp64, NULL); +} + +COMPAT_SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock, +		       struct compat_timespec __user *,tp)  { -	return hrtimer_nanosleep_restart(restart_block); +	struct timespec64 kernel_tp64; +	struct timespec kernel_tp; + +	switch (which_clock) { +	case CLOCK_REALTIME: ktime_get_real_ts64(&kernel_tp64); break; +	case CLOCK_MONOTONIC: ktime_get_ts64(&kernel_tp64); break; +	case CLOCK_BOOTTIME: get_monotonic_boottime64(&kernel_tp64); break; +	default: return -EINVAL; +	} + +	kernel_tp = timespec64_to_timespec(kernel_tp64); +	if (compat_put_timespec(&kernel_tp, tp)) +		return -EFAULT; +	return 0; +} + +COMPAT_SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock, +		       struct compat_timespec __user *, tp) +{ +	struct timespec rtn_tp = { +		.tv_sec = 0, +		.tv_nsec = hrtimer_resolution, +	}; + +	switch (which_clock) { +	case CLOCK_REALTIME: +	case CLOCK_MONOTONIC: +	case CLOCK_BOOTTIME: +		if (compat_put_timespec(&rtn_tp, tp)) +			return -EFAULT; +		return 0; +	default: +		return -EINVAL; +	} +} +COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags, +		       struct compat_timespec __user *, rqtp, +		       struct compat_timespec __user *, rmtp) +{ +	struct timespec64 t64; +	struct timespec t; + +	switch (which_clock) { +	case CLOCK_REALTIME: +	case CLOCK_MONOTONIC: +	case CLOCK_BOOTTIME: +		break; +	default: +		return -EINVAL; +	} + +	if (compat_get_timespec(&t, rqtp)) +		return -EFAULT; +	t64 = timespec_to_timespec64(t); +	if (!timespec64_valid(&t64)) +		return -EINVAL; +	if (flags & TIMER_ABSTIME) +		rmtp = NULL; +	current->restart_block.nanosleep.type = rmtp ? TT_COMPAT : TT_NONE; +	current->restart_block.nanosleep.compat_rmtp = rmtp; +	return hrtimer_nanosleep(&t64, flags & TIMER_ABSTIME ? +				 HRTIMER_MODE_ABS : HRTIMER_MODE_REL, +				 which_clock);  }  #endif diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c index 4d7b2ce09c27..82d67be7d9d1 100644 --- a/kernel/time/posix-timers.c +++ b/kernel/time/posix-timers.c @@ -49,8 +49,10 @@  #include <linux/workqueue.h>  #include <linux/export.h>  #include <linux/hashtable.h> +#include <linux/compat.h>  #include "timekeeping.h" +#include "posix-timers.h"  /*   * Management arrays for POSIX timers. Timers are now kept in static hash table @@ -69,6 +71,10 @@ static struct kmem_cache *posix_timers_cache;  static DEFINE_HASHTABLE(posix_timers_hashtable, 9);  static DEFINE_SPINLOCK(hash_lock); +static const struct k_clock * const posix_clocks[]; +static const struct k_clock *clockid_to_kclock(const clockid_t id); +static const struct k_clock clock_realtime, clock_monotonic; +  /*   * we assume that the new SIGEV_THREAD_ID shares no bits with the other   * SIGEV values.  Here we put out an error if this assumption fails. @@ -124,22 +130,6 @@ static DEFINE_SPINLOCK(hash_lock);   *	    have is CLOCK_REALTIME and its high res counter part, both of   *	    which we beg off on and pass to do_sys_settimeofday().   */ - -static struct k_clock posix_clocks[MAX_CLOCKS]; - -/* - * These ones are defined below. - */ -static int common_nsleep(const clockid_t, int flags, struct timespec64 *t, -			 struct timespec __user *rmtp); -static int common_timer_create(struct k_itimer *new_timer); -static void common_timer_get(struct k_itimer *, struct itimerspec64 *); -static int common_timer_set(struct k_itimer *, int, -			    struct itimerspec64 *, struct itimerspec64 *); -static int common_timer_del(struct k_itimer *timer); - -static enum hrtimer_restart posix_timer_fn(struct hrtimer *data); -  static struct k_itimer *__lock_timer(timer_t timer_id, unsigned long *flags);  #define lock_timer(tid, flags)						   \ @@ -285,91 +275,23 @@ static int posix_get_hrtimer_res(clockid_t which_clock, struct timespec64 *tp)   */  static __init int init_posix_timers(void)  { -	struct k_clock clock_realtime = { -		.clock_getres	= posix_get_hrtimer_res, -		.clock_get	= posix_clock_realtime_get, -		.clock_set	= posix_clock_realtime_set, -		.clock_adj	= posix_clock_realtime_adj, -		.nsleep		= common_nsleep, -		.nsleep_restart	= hrtimer_nanosleep_restart, -		.timer_create	= common_timer_create, -		.timer_set	= common_timer_set, -		.timer_get	= common_timer_get, -		.timer_del	= common_timer_del, -	}; -	struct k_clock clock_monotonic = { -		.clock_getres	= posix_get_hrtimer_res, -		.clock_get	= posix_ktime_get_ts, -		.nsleep		= common_nsleep, -		.nsleep_restart	= hrtimer_nanosleep_restart, -		.timer_create	= common_timer_create, -		.timer_set	= common_timer_set, -		.timer_get	= common_timer_get, -		.timer_del	= common_timer_del, -	}; -	struct k_clock clock_monotonic_raw = { -		.clock_getres	= posix_get_hrtimer_res, -		.clock_get	= posix_get_monotonic_raw, -	}; -	struct k_clock clock_realtime_coarse = { -		.clock_getres	= posix_get_coarse_res, -		.clock_get	= posix_get_realtime_coarse, -	}; -	struct k_clock clock_monotonic_coarse = { -		.clock_getres	= posix_get_coarse_res, -		.clock_get	= posix_get_monotonic_coarse, -	}; -	struct k_clock clock_tai = { -		.clock_getres	= posix_get_hrtimer_res, -		.clock_get	= posix_get_tai, -		.nsleep		= common_nsleep, -		.nsleep_restart	= hrtimer_nanosleep_restart, -		.timer_create	= common_timer_create, -		.timer_set	= common_timer_set, -		.timer_get	= common_timer_get, -		.timer_del	= common_timer_del, -	}; -	struct k_clock clock_boottime = { -		.clock_getres	= posix_get_hrtimer_res, -		.clock_get	= posix_get_boottime, -		.nsleep		= common_nsleep, -		.nsleep_restart	= hrtimer_nanosleep_restart, -		.timer_create	= common_timer_create, -		.timer_set	= common_timer_set, -		.timer_get	= common_timer_get, -		.timer_del	= common_timer_del, -	}; - -	posix_timers_register_clock(CLOCK_REALTIME, &clock_realtime); -	posix_timers_register_clock(CLOCK_MONOTONIC, &clock_monotonic); -	posix_timers_register_clock(CLOCK_MONOTONIC_RAW, &clock_monotonic_raw); -	posix_timers_register_clock(CLOCK_REALTIME_COARSE, &clock_realtime_coarse); -	posix_timers_register_clock(CLOCK_MONOTONIC_COARSE, &clock_monotonic_coarse); -	posix_timers_register_clock(CLOCK_BOOTTIME, &clock_boottime); -	posix_timers_register_clock(CLOCK_TAI, &clock_tai); -  	posix_timers_cache = kmem_cache_create("posix_timers_cache",  					sizeof (struct k_itimer), 0, SLAB_PANIC,  					NULL);  	return 0;  } -  __initcall(init_posix_timers); -static void schedule_next_timer(struct k_itimer *timr) +static void common_hrtimer_rearm(struct k_itimer *timr)  {  	struct hrtimer *timer = &timr->it.real.timer; -	if (timr->it.real.interval == 0) +	if (!timr->it_interval)  		return;  	timr->it_overrun += (unsigned int) hrtimer_forward(timer,  						timer->base->get_time(), -						timr->it.real.interval); - -	timr->it_overrun_last = timr->it_overrun; -	timr->it_overrun = -1; -	++timr->it_requeue_pending; +						timr->it_interval);  	hrtimer_restart(timer);  } @@ -384,24 +306,27 @@ static void schedule_next_timer(struct k_itimer *timr)   * To protect against the timer going away while the interrupt is queued,   * we require that the it_requeue_pending flag be set.   */ -void do_schedule_next_timer(struct siginfo *info) +void posixtimer_rearm(struct siginfo *info)  {  	struct k_itimer *timr;  	unsigned long flags;  	timr = lock_timer(info->si_tid, &flags); +	if (!timr) +		return; -	if (timr && timr->it_requeue_pending == info->si_sys_private) { -		if (timr->it_clock < 0) -			posix_cpu_timer_schedule(timr); -		else -			schedule_next_timer(timr); +	if (timr->it_requeue_pending == info->si_sys_private) { +		timr->kclock->timer_rearm(timr); + +		timr->it_active = 1; +		timr->it_overrun_last = timr->it_overrun; +		timr->it_overrun = -1; +		++timr->it_requeue_pending;  		info->si_overrun += timr->it_overrun_last;  	} -	if (timr) -		unlock_timer(timr, flags); +	unlock_timer(timr, flags);  }  int posix_timer_event(struct k_itimer *timr, int si_private) @@ -410,12 +335,12 @@ int posix_timer_event(struct k_itimer *timr, int si_private)  	int shared, ret = -1;  	/*  	 * FIXME: if ->sigq is queued we can race with -	 * dequeue_signal()->do_schedule_next_timer(). +	 * dequeue_signal()->posixtimer_rearm().  	 *  	 * If dequeue_signal() sees the "right" value of -	 * si_sys_private it calls do_schedule_next_timer(). +	 * si_sys_private it calls posixtimer_rearm().  	 * We re-queue ->sigq and drop ->it_lock(). -	 * do_schedule_next_timer() locks the timer +	 * posixtimer_rearm() locks the timer  	 * and re-schedules it while ->sigq is pending.  	 * Not really bad, but not that we want.  	 */ @@ -431,7 +356,6 @@ int posix_timer_event(struct k_itimer *timr, int si_private)  	/* If we failed to send the signal the timer stops. */  	return ret > 0;  } -EXPORT_SYMBOL_GPL(posix_timer_event);  /*   * This function gets called when a POSIX.1b interval timer expires.  It @@ -450,7 +374,8 @@ static enum hrtimer_restart posix_timer_fn(struct hrtimer *timer)  	timr = container_of(timer, struct k_itimer, it.real.timer);  	spin_lock_irqsave(&timr->it_lock, flags); -	if (timr->it.real.interval != 0) +	timr->it_active = 0; +	if (timr->it_interval != 0)  		si_private = ++timr->it_requeue_pending;  	if (posix_timer_event(timr, si_private)) { @@ -459,7 +384,7 @@ static enum hrtimer_restart posix_timer_fn(struct hrtimer *timer)  		 * we will not get a call back to restart it AND  		 * it should be restarted.  		 */ -		if (timr->it.real.interval != 0) { +		if (timr->it_interval != 0) {  			ktime_t now = hrtimer_cb_get_time(timer);  			/* @@ -488,15 +413,16 @@ static enum hrtimer_restart posix_timer_fn(struct hrtimer *timer)  			{  				ktime_t kj = NSEC_PER_SEC / HZ; -				if (timr->it.real.interval < kj) +				if (timr->it_interval < kj)  					now = ktime_add(now, kj);  			}  #endif  			timr->it_overrun += (unsigned int)  				hrtimer_forward(timer, now, -						timr->it.real.interval); +						timr->it_interval);  			ret = HRTIMER_RESTART;  			++timr->it_requeue_pending; +			timr->it_active = 1;  		}  	} @@ -521,30 +447,6 @@ static struct pid *good_sigevent(sigevent_t * event)  	return task_pid(rtn);  } -void posix_timers_register_clock(const clockid_t clock_id, -				 struct k_clock *new_clock) -{ -	if ((unsigned) clock_id >= MAX_CLOCKS) { -		printk(KERN_WARNING "POSIX clock register failed for clock_id %d\n", -		       clock_id); -		return; -	} - -	if (!new_clock->clock_get) { -		printk(KERN_WARNING "POSIX clock id %d lacks clock_get()\n", -		       clock_id); -		return; -	} -	if (!new_clock->clock_getres) { -		printk(KERN_WARNING "POSIX clock id %d lacks clock_getres()\n", -		       clock_id); -		return; -	} - -	posix_clocks[clock_id] = *new_clock; -} -EXPORT_SYMBOL_GPL(posix_timers_register_clock); -  static struct k_itimer * alloc_posix_timer(void)  {  	struct k_itimer *tmr; @@ -581,17 +483,6 @@ static void release_posix_timer(struct k_itimer *tmr, int it_id_set)  	call_rcu(&tmr->it.rcu, k_itimer_rcu_free);  } -static struct k_clock *clockid_to_kclock(const clockid_t id) -{ -	if (id < 0) -		return (id & CLOCKFD_MASK) == CLOCKFD ? -			&clock_posix_dynamic : &clock_posix_cpu; - -	if (id >= MAX_CLOCKS || !posix_clocks[id].clock_getres) -		return NULL; -	return &posix_clocks[id]; -} -  static int common_timer_create(struct k_itimer *new_timer)  {  	hrtimer_init(&new_timer->it.real.timer, new_timer->it_clock, 0); @@ -599,15 +490,12 @@ static int common_timer_create(struct k_itimer *new_timer)  }  /* Create a POSIX.1b interval timer. */ - -SYSCALL_DEFINE3(timer_create, const clockid_t, which_clock, -		struct sigevent __user *, timer_event_spec, -		timer_t __user *, created_timer_id) +static int do_timer_create(clockid_t which_clock, struct sigevent *event, +			   timer_t __user *created_timer_id)  { -	struct k_clock *kc = clockid_to_kclock(which_clock); +	const struct k_clock *kc = clockid_to_kclock(which_clock);  	struct k_itimer *new_timer;  	int error, new_timer_id; -	sigevent_t event;  	int it_id_set = IT_ID_NOT_SET;  	if (!kc) @@ -629,31 +517,28 @@ SYSCALL_DEFINE3(timer_create, const clockid_t, which_clock,  	it_id_set = IT_ID_SET;  	new_timer->it_id = (timer_t) new_timer_id;  	new_timer->it_clock = which_clock; +	new_timer->kclock = kc;  	new_timer->it_overrun = -1; -	if (timer_event_spec) { -		if (copy_from_user(&event, timer_event_spec, sizeof (event))) { -			error = -EFAULT; -			goto out; -		} +	if (event) {  		rcu_read_lock(); -		new_timer->it_pid = get_pid(good_sigevent(&event)); +		new_timer->it_pid = get_pid(good_sigevent(event));  		rcu_read_unlock();  		if (!new_timer->it_pid) {  			error = -EINVAL;  			goto out;  		} +		new_timer->it_sigev_notify     = event->sigev_notify; +		new_timer->sigq->info.si_signo = event->sigev_signo; +		new_timer->sigq->info.si_value = event->sigev_value;  	} else { -		memset(&event.sigev_value, 0, sizeof(event.sigev_value)); -		event.sigev_notify = SIGEV_SIGNAL; -		event.sigev_signo = SIGALRM; -		event.sigev_value.sival_int = new_timer->it_id; +		new_timer->it_sigev_notify     = SIGEV_SIGNAL; +		new_timer->sigq->info.si_signo = SIGALRM; +		memset(&new_timer->sigq->info.si_value, 0, sizeof(sigval_t)); +		new_timer->sigq->info.si_value.sival_int = new_timer->it_id;  		new_timer->it_pid = get_pid(task_tgid(current));  	} -	new_timer->it_sigev_notify     = event.sigev_notify; -	new_timer->sigq->info.si_signo = event.sigev_signo; -	new_timer->sigq->info.si_value = event.sigev_value;  	new_timer->sigq->info.si_tid   = new_timer->it_id;  	new_timer->sigq->info.si_code  = SI_TIMER; @@ -684,6 +569,36 @@ out:  	return error;  } +SYSCALL_DEFINE3(timer_create, const clockid_t, which_clock, +		struct sigevent __user *, timer_event_spec, +		timer_t __user *, created_timer_id) +{ +	if (timer_event_spec) { +		sigevent_t event; + +		if (copy_from_user(&event, timer_event_spec, sizeof (event))) +			return -EFAULT; +		return do_timer_create(which_clock, &event, created_timer_id); +	} +	return do_timer_create(which_clock, NULL, created_timer_id); +} + +#ifdef CONFIG_COMPAT +COMPAT_SYSCALL_DEFINE3(timer_create, clockid_t, which_clock, +		       struct compat_sigevent __user *, timer_event_spec, +		       timer_t __user *, created_timer_id) +{ +	if (timer_event_spec) { +		sigevent_t event; + +		if (get_compat_sigevent(&event, timer_event_spec)) +			return -EFAULT; +		return do_timer_create(which_clock, &event, created_timer_id); +	} +	return do_timer_create(which_clock, NULL, created_timer_id); +} +#endif +  /*   * Locking issues: We need to protect the result of the id look up until   * we get the timer locked down so it is not deleted under us.  The @@ -717,6 +632,20 @@ static struct k_itimer *__lock_timer(timer_t timer_id, unsigned long *flags)  	return NULL;  } +static ktime_t common_hrtimer_remaining(struct k_itimer *timr, ktime_t now) +{ +	struct hrtimer *timer = &timr->it.real.timer; + +	return __hrtimer_expires_remaining_adjusted(timer, now); +} + +static int common_hrtimer_forward(struct k_itimer *timr, ktime_t now) +{ +	struct hrtimer *timer = &timr->it.real.timer; + +	return (int)hrtimer_forward(timer, now, timr->it_interval); +} +  /*   * Get the time remaining on a POSIX.1b interval timer.  This function   * is ALWAYS called with spin_lock_irq on the timer, thus it must not @@ -733,55 +662,61 @@ static struct k_itimer *__lock_timer(timer_t timer_id, unsigned long *flags)   * it is the same as a requeue pending timer WRT to what we should   * report.   */ -static void -common_timer_get(struct k_itimer *timr, struct itimerspec64 *cur_setting) +void common_timer_get(struct k_itimer *timr, struct itimerspec64 *cur_setting)  { +	const struct k_clock *kc = timr->kclock;  	ktime_t now, remaining, iv; -	struct hrtimer *timer = &timr->it.real.timer; +	struct timespec64 ts64; +	bool sig_none; -	memset(cur_setting, 0, sizeof(*cur_setting)); - -	iv = timr->it.real.interval; +	sig_none = (timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE; +	iv = timr->it_interval;  	/* interval timer ? */ -	if (iv) +	if (iv) {  		cur_setting->it_interval = ktime_to_timespec64(iv); -	else if (!hrtimer_active(timer) && -		 (timr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) -		return; +	} else if (!timr->it_active) { +		/* +		 * SIGEV_NONE oneshot timers are never queued. Check them +		 * below. +		 */ +		if (!sig_none) +			return; +	} -	now = timer->base->get_time(); +	/* +	 * The timespec64 based conversion is suboptimal, but it's not +	 * worth to implement yet another callback. +	 */ +	kc->clock_get(timr->it_clock, &ts64); +	now = timespec64_to_ktime(ts64);  	/* -	 * When a requeue is pending or this is a SIGEV_NONE -	 * timer move the expiry time forward by intervals, so -	 * expiry is > now. +	 * When a requeue is pending or this is a SIGEV_NONE timer move the +	 * expiry time forward by intervals, so expiry is > now.  	 */ -	if (iv && (timr->it_requeue_pending & REQUEUE_PENDING || -		   (timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE)) -		timr->it_overrun += (unsigned int) hrtimer_forward(timer, now, iv); +	if (iv && (timr->it_requeue_pending & REQUEUE_PENDING || sig_none)) +		timr->it_overrun += kc->timer_forward(timr, now); -	remaining = __hrtimer_expires_remaining_adjusted(timer, now); +	remaining = kc->timer_remaining(timr, now);  	/* Return 0 only, when the timer is expired and not pending */  	if (remaining <= 0) {  		/*  		 * A single shot SIGEV_NONE timer must return 0, when  		 * it is expired !  		 */ -		if ((timr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) +		if (!sig_none)  			cur_setting->it_value.tv_nsec = 1; -	} else +	} else {  		cur_setting->it_value = ktime_to_timespec64(remaining); +	}  }  /* Get the time remaining on a POSIX.1b interval timer. */ -SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id, -		struct itimerspec __user *, setting) +static int do_timer_gettime(timer_t timer_id,  struct itimerspec64 *setting)  { -	struct itimerspec64 cur_setting64; -	struct itimerspec cur_setting;  	struct k_itimer *timr; -	struct k_clock *kc; +	const struct k_clock *kc;  	unsigned long flags;  	int ret = 0; @@ -789,20 +724,49 @@ SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id,  	if (!timr)  		return -EINVAL; -	kc = clockid_to_kclock(timr->it_clock); +	memset(setting, 0, sizeof(*setting)); +	kc = timr->kclock;  	if (WARN_ON_ONCE(!kc || !kc->timer_get))  		ret = -EINVAL;  	else -		kc->timer_get(timr, &cur_setting64); +		kc->timer_get(timr, setting);  	unlock_timer(timr, flags); +	return ret; +} -	cur_setting = itimerspec64_to_itimerspec(&cur_setting64); -	if (!ret && copy_to_user(setting, &cur_setting, sizeof (cur_setting))) -		return -EFAULT; +/* Get the time remaining on a POSIX.1b interval timer. */ +SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id, +		struct itimerspec __user *, setting) +{ +	struct itimerspec64 cur_setting64; +	int ret = do_timer_gettime(timer_id, &cur_setting64); +	if (!ret) { +		struct itimerspec cur_setting; +		cur_setting = itimerspec64_to_itimerspec(&cur_setting64); +		if (copy_to_user(setting, &cur_setting, sizeof (cur_setting))) +			ret = -EFAULT; +	} +	return ret; +} + +#ifdef CONFIG_COMPAT +COMPAT_SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id, +		       struct compat_itimerspec __user *, setting) +{ +	struct itimerspec64 cur_setting64; + +	int ret = do_timer_gettime(timer_id, &cur_setting64); +	if (!ret) { +		struct itimerspec cur_setting; +		cur_setting = itimerspec64_to_itimerspec(&cur_setting64); +		if (put_compat_itimerspec(setting, &cur_setting)) +			ret = -EFAULT; +	}  	return ret;  } +#endif  /*   * Get the number of overruns of a POSIX.1b interval timer.  This is to @@ -810,7 +774,7 @@ SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id,   * accumulating overruns on the next timer.  The overrun is frozen when   * the signal is delivered, either at the notify time (if the info block   * is not queued) or at the actual delivery time (as we are informed by - * the call back to do_schedule_next_timer().  So all we need to do is + * the call back to posixtimer_rearm().  So all we need to do is   * to pick up the frozen overrun.   */  SYSCALL_DEFINE1(timer_getoverrun, timer_t, timer_id) @@ -829,117 +793,183 @@ SYSCALL_DEFINE1(timer_getoverrun, timer_t, timer_id)  	return overrun;  } -/* Set a POSIX.1b interval timer. */ -/* timr->it_lock is taken. */ -static int -common_timer_set(struct k_itimer *timr, int flags, -		 struct itimerspec64 *new_setting, struct itimerspec64 *old_setting) +static void common_hrtimer_arm(struct k_itimer *timr, ktime_t expires, +			       bool absolute, bool sigev_none)  {  	struct hrtimer *timer = &timr->it.real.timer;  	enum hrtimer_mode mode; +	mode = absolute ? HRTIMER_MODE_ABS : HRTIMER_MODE_REL; +	/* +	 * Posix magic: Relative CLOCK_REALTIME timers are not affected by +	 * clock modifications, so they become CLOCK_MONOTONIC based under the +	 * hood. See hrtimer_init(). Update timr->kclock, so the generic +	 * functions which use timr->kclock->clock_get() work. +	 * +	 * Note: it_clock stays unmodified, because the next timer_set() might +	 * use ABSTIME, so it needs to switch back. +	 */ +	if (timr->it_clock == CLOCK_REALTIME) +		timr->kclock = absolute ? &clock_realtime : &clock_monotonic; + +	hrtimer_init(&timr->it.real.timer, timr->it_clock, mode); +	timr->it.real.timer.function = posix_timer_fn; + +	if (!absolute) +		expires = ktime_add_safe(expires, timer->base->get_time()); +	hrtimer_set_expires(timer, expires); + +	if (!sigev_none) +		hrtimer_start_expires(timer, HRTIMER_MODE_ABS); +} + +static int common_hrtimer_try_to_cancel(struct k_itimer *timr) +{ +	return hrtimer_try_to_cancel(&timr->it.real.timer); +} + +/* Set a POSIX.1b interval timer. */ +int common_timer_set(struct k_itimer *timr, int flags, +		     struct itimerspec64 *new_setting, +		     struct itimerspec64 *old_setting) +{ +	const struct k_clock *kc = timr->kclock; +	bool sigev_none; +	ktime_t expires; +  	if (old_setting)  		common_timer_get(timr, old_setting); -	/* disable the timer */ -	timr->it.real.interval = 0; +	/* Prevent rearming by clearing the interval */ +	timr->it_interval = 0;  	/* -	 * careful here.  If smp we could be in the "fire" routine which will -	 * be spinning as we hold the lock.  But this is ONLY an SMP issue. +	 * Careful here. On SMP systems the timer expiry function could be +	 * active and spinning on timr->it_lock.  	 */ -	if (hrtimer_try_to_cancel(timer) < 0) +	if (kc->timer_try_to_cancel(timr) < 0)  		return TIMER_RETRY; -	timr->it_requeue_pending = (timr->it_requeue_pending + 2) &  +	timr->it_active = 0; +	timr->it_requeue_pending = (timr->it_requeue_pending + 2) &  		~REQUEUE_PENDING;  	timr->it_overrun_last = 0; -	/* switch off the timer when it_value is zero */ +	/* Switch off the timer when it_value is zero */  	if (!new_setting->it_value.tv_sec && !new_setting->it_value.tv_nsec)  		return 0; -	mode = flags & TIMER_ABSTIME ? HRTIMER_MODE_ABS : HRTIMER_MODE_REL; -	hrtimer_init(&timr->it.real.timer, timr->it_clock, mode); -	timr->it.real.timer.function = posix_timer_fn; - -	hrtimer_set_expires(timer, timespec64_to_ktime(new_setting->it_value)); - -	/* Convert interval */ -	timr->it.real.interval = timespec64_to_ktime(new_setting->it_interval); - -	/* SIGEV_NONE timers are not queued ! See common_timer_get */ -	if (((timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE)) { -		/* Setup correct expiry time for relative timers */ -		if (mode == HRTIMER_MODE_REL) { -			hrtimer_add_expires(timer, timer->base->get_time()); -		} -		return 0; -	} +	timr->it_interval = timespec64_to_ktime(new_setting->it_interval); +	expires = timespec64_to_ktime(new_setting->it_value); +	sigev_none = (timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE; -	hrtimer_start_expires(timer, mode); +	kc->timer_arm(timr, expires, flags & TIMER_ABSTIME, sigev_none); +	timr->it_active = !sigev_none;  	return 0;  } -/* Set a POSIX.1b interval timer */ -SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags, -		const struct itimerspec __user *, new_setting, -		struct itimerspec __user *, old_setting) +static int do_timer_settime(timer_t timer_id, int flags, +			    struct itimerspec64 *new_spec64, +			    struct itimerspec64 *old_spec64)  { -	struct itimerspec64 new_spec64, old_spec64; -	struct itimerspec64 *rtn = old_setting ? &old_spec64 : NULL; -	struct itimerspec new_spec, old_spec; +	const struct k_clock *kc;  	struct k_itimer *timr;  	unsigned long flag; -	struct k_clock *kc;  	int error = 0; -	if (!new_setting) +	if (!timespec64_valid(&new_spec64->it_interval) || +	    !timespec64_valid(&new_spec64->it_value))  		return -EINVAL; -	if (copy_from_user(&new_spec, new_setting, sizeof (new_spec))) -		return -EFAULT; -	new_spec64 = itimerspec_to_itimerspec64(&new_spec); - -	if (!timespec64_valid(&new_spec64.it_interval) || -	    !timespec64_valid(&new_spec64.it_value)) -		return -EINVAL; +	if (old_spec64) +		memset(old_spec64, 0, sizeof(*old_spec64));  retry:  	timr = lock_timer(timer_id, &flag);  	if (!timr)  		return -EINVAL; -	kc = clockid_to_kclock(timr->it_clock); +	kc = timr->kclock;  	if (WARN_ON_ONCE(!kc || !kc->timer_set))  		error = -EINVAL;  	else -		error = kc->timer_set(timr, flags, &new_spec64, rtn); +		error = kc->timer_set(timr, flags, new_spec64, old_spec64);  	unlock_timer(timr, flag);  	if (error == TIMER_RETRY) { -		rtn = NULL;	// We already got the old time... +		old_spec64 = NULL;	// We already got the old time...  		goto retry;  	} -	old_spec = itimerspec64_to_itimerspec(&old_spec64); -	if (old_setting && !error && -	    copy_to_user(old_setting, &old_spec, sizeof (old_spec))) -		error = -EFAULT; +	return error; +} + +/* Set a POSIX.1b interval timer */ +SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags, +		const struct itimerspec __user *, new_setting, +		struct itimerspec __user *, old_setting) +{ +	struct itimerspec64 new_spec64, old_spec64; +	struct itimerspec64 *rtn = old_setting ? &old_spec64 : NULL; +	struct itimerspec new_spec; +	int error = 0; + +	if (!new_setting) +		return -EINVAL; + +	if (copy_from_user(&new_spec, new_setting, sizeof (new_spec))) +		return -EFAULT; +	new_spec64 = itimerspec_to_itimerspec64(&new_spec); + +	error = do_timer_settime(timer_id, flags, &new_spec64, rtn); +	if (!error && old_setting) { +		struct itimerspec old_spec; +		old_spec = itimerspec64_to_itimerspec(&old_spec64); +		if (copy_to_user(old_setting, &old_spec, sizeof (old_spec))) +			error = -EFAULT; +	} +	return error; +} + +#ifdef CONFIG_COMPAT +COMPAT_SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags, +		       struct compat_itimerspec __user *, new, +		       struct compat_itimerspec __user *, old) +{ +	struct itimerspec64 new_spec64, old_spec64; +	struct itimerspec64 *rtn = old ? &old_spec64 : NULL; +	struct itimerspec new_spec; +	int error = 0; + +	if (!new) +		return -EINVAL; +	if (get_compat_itimerspec(&new_spec, new)) +		return -EFAULT; +	new_spec64 = itimerspec_to_itimerspec64(&new_spec); +	error = do_timer_settime(timer_id, flags, &new_spec64, rtn); +	if (!error && old) { +		struct itimerspec old_spec; +		old_spec = itimerspec64_to_itimerspec(&old_spec64); +		if (put_compat_itimerspec(old, &old_spec)) +			error = -EFAULT; +	}  	return error;  } +#endif -static int common_timer_del(struct k_itimer *timer) +int common_timer_del(struct k_itimer *timer)  { -	timer->it.real.interval = 0; +	const struct k_clock *kc = timer->kclock; -	if (hrtimer_try_to_cancel(&timer->it.real.timer) < 0) +	timer->it_interval = 0; +	if (kc->timer_try_to_cancel(timer) < 0)  		return TIMER_RETRY; +	timer->it_active = 0;  	return 0;  }  static inline int timer_delete_hook(struct k_itimer *timer)  { -	struct k_clock *kc = clockid_to_kclock(timer->it_clock); +	const struct k_clock *kc = timer->kclock;  	if (WARN_ON_ONCE(!kc || !kc->timer_del))  		return -EINVAL; @@ -1018,7 +1048,7 @@ void exit_itimers(struct signal_struct *sig)  SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock,  		const struct timespec __user *, tp)  { -	struct k_clock *kc = clockid_to_kclock(which_clock); +	const struct k_clock *kc = clockid_to_kclock(which_clock);  	struct timespec64 new_tp64;  	struct timespec new_tp; @@ -1035,7 +1065,7 @@ SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock,  SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock,  		struct timespec __user *,tp)  { -	struct k_clock *kc = clockid_to_kclock(which_clock); +	const struct k_clock *kc = clockid_to_kclock(which_clock);  	struct timespec64 kernel_tp64;  	struct timespec kernel_tp;  	int error; @@ -1055,7 +1085,7 @@ SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock,  SYSCALL_DEFINE2(clock_adjtime, const clockid_t, which_clock,  		struct timex __user *, utx)  { -	struct k_clock *kc = clockid_to_kclock(which_clock); +	const struct k_clock *kc = clockid_to_kclock(which_clock);  	struct timex ktx;  	int err; @@ -1078,7 +1108,7 @@ SYSCALL_DEFINE2(clock_adjtime, const clockid_t, which_clock,  SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock,  		struct timespec __user *, tp)  { -	struct k_clock *kc = clockid_to_kclock(which_clock); +	const struct k_clock *kc = clockid_to_kclock(which_clock);  	struct timespec64 rtn_tp64;  	struct timespec rtn_tp;  	int error; @@ -1095,13 +1125,98 @@ SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock,  	return error;  } +#ifdef CONFIG_COMPAT + +COMPAT_SYSCALL_DEFINE2(clock_settime, clockid_t, which_clock, +		       struct compat_timespec __user *, tp) +{ +	const struct k_clock *kc = clockid_to_kclock(which_clock); +	struct timespec64 new_tp64; +	struct timespec new_tp; + +	if (!kc || !kc->clock_set) +		return -EINVAL; + +	if (compat_get_timespec(&new_tp, tp)) +		return -EFAULT; + +	new_tp64 = timespec_to_timespec64(new_tp); + +	return kc->clock_set(which_clock, &new_tp64); +} + +COMPAT_SYSCALL_DEFINE2(clock_gettime, clockid_t, which_clock, +		       struct compat_timespec __user *, tp) +{ +	const struct k_clock *kc = clockid_to_kclock(which_clock); +	struct timespec64 kernel_tp64; +	struct timespec kernel_tp; +	int error; + +	if (!kc) +		return -EINVAL; + +	error = kc->clock_get(which_clock, &kernel_tp64); +	kernel_tp = timespec64_to_timespec(kernel_tp64); + +	if (!error && compat_put_timespec(&kernel_tp, tp)) +		error = -EFAULT; + +	return error; +} + +COMPAT_SYSCALL_DEFINE2(clock_adjtime, clockid_t, which_clock, +		       struct compat_timex __user *, utp) +{ +	const struct k_clock *kc = clockid_to_kclock(which_clock); +	struct timex ktx; +	int err; + +	if (!kc) +		return -EINVAL; +	if (!kc->clock_adj) +		return -EOPNOTSUPP; + +	err = compat_get_timex(&ktx, utp); +	if (err) +		return err; + +	err = kc->clock_adj(which_clock, &ktx); + +	if (err >= 0) +		err = compat_put_timex(utp, &ktx); + +	return err; +} + +COMPAT_SYSCALL_DEFINE2(clock_getres, clockid_t, which_clock, +		       struct compat_timespec __user *, tp) +{ +	const struct k_clock *kc = clockid_to_kclock(which_clock); +	struct timespec64 rtn_tp64; +	struct timespec rtn_tp; +	int error; + +	if (!kc) +		return -EINVAL; + +	error = kc->clock_getres(which_clock, &rtn_tp64); +	rtn_tp = timespec64_to_timespec(rtn_tp64); + +	if (!error && tp && compat_put_timespec(&rtn_tp, tp)) +		error = -EFAULT; + +	return error; +} +#endif +  /*   * nanosleep for monotonic and realtime clocks   */  static int common_nsleep(const clockid_t which_clock, int flags, -			 struct timespec64 *tsave, struct timespec __user *rmtp) +			 const struct timespec64 *rqtp)  { -	return hrtimer_nanosleep(tsave, rmtp, flags & TIMER_ABSTIME ? +	return hrtimer_nanosleep(rqtp, flags & TIMER_ABSTIME ?  				 HRTIMER_MODE_ABS : HRTIMER_MODE_REL,  				 which_clock);  } @@ -1110,7 +1225,7 @@ SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags,  		const struct timespec __user *, rqtp,  		struct timespec __user *, rmtp)  { -	struct k_clock *kc = clockid_to_kclock(which_clock); +	const struct k_clock *kc = clockid_to_kclock(which_clock);  	struct timespec64 t64;  	struct timespec t; @@ -1125,21 +1240,141 @@ SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags,  	t64 = timespec_to_timespec64(t);  	if (!timespec64_valid(&t64))  		return -EINVAL; +	if (flags & TIMER_ABSTIME) +		rmtp = NULL; +	current->restart_block.nanosleep.type = rmtp ? TT_NATIVE : TT_NONE; +	current->restart_block.nanosleep.rmtp = rmtp; -	return kc->nsleep(which_clock, flags, &t64, rmtp); +	return kc->nsleep(which_clock, flags, &t64);  } -/* - * This will restart clock_nanosleep. This is required only by - * compat_clock_nanosleep_restart for now. - */ -long clock_nanosleep_restart(struct restart_block *restart_block) +#ifdef CONFIG_COMPAT +COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags, +		       struct compat_timespec __user *, rqtp, +		       struct compat_timespec __user *, rmtp)  { -	clockid_t which_clock = restart_block->nanosleep.clockid; -	struct k_clock *kc = clockid_to_kclock(which_clock); +	const struct k_clock *kc = clockid_to_kclock(which_clock); +	struct timespec64 t64; +	struct timespec t; -	if (WARN_ON_ONCE(!kc || !kc->nsleep_restart)) +	if (!kc)  		return -EINVAL; +	if (!kc->nsleep) +		return -ENANOSLEEP_NOTSUP; -	return kc->nsleep_restart(restart_block); +	if (compat_get_timespec(&t, rqtp)) +		return -EFAULT; + +	t64 = timespec_to_timespec64(t); +	if (!timespec64_valid(&t64)) +		return -EINVAL; +	if (flags & TIMER_ABSTIME) +		rmtp = NULL; +	current->restart_block.nanosleep.type = rmtp ? TT_COMPAT : TT_NONE; +	current->restart_block.nanosleep.compat_rmtp = rmtp; + +	return kc->nsleep(which_clock, flags, &t64); +} +#endif + +static const struct k_clock clock_realtime = { +	.clock_getres		= posix_get_hrtimer_res, +	.clock_get		= posix_clock_realtime_get, +	.clock_set		= posix_clock_realtime_set, +	.clock_adj		= posix_clock_realtime_adj, +	.nsleep			= common_nsleep, +	.timer_create		= common_timer_create, +	.timer_set		= common_timer_set, +	.timer_get		= common_timer_get, +	.timer_del		= common_timer_del, +	.timer_rearm		= common_hrtimer_rearm, +	.timer_forward		= common_hrtimer_forward, +	.timer_remaining	= common_hrtimer_remaining, +	.timer_try_to_cancel	= common_hrtimer_try_to_cancel, +	.timer_arm		= common_hrtimer_arm, +}; + +static const struct k_clock clock_monotonic = { +	.clock_getres		= posix_get_hrtimer_res, +	.clock_get		= posix_ktime_get_ts, +	.nsleep			= common_nsleep, +	.timer_create		= common_timer_create, +	.timer_set		= common_timer_set, +	.timer_get		= common_timer_get, +	.timer_del		= common_timer_del, +	.timer_rearm		= common_hrtimer_rearm, +	.timer_forward		= common_hrtimer_forward, +	.timer_remaining	= common_hrtimer_remaining, +	.timer_try_to_cancel	= common_hrtimer_try_to_cancel, +	.timer_arm		= common_hrtimer_arm, +}; + +static const struct k_clock clock_monotonic_raw = { +	.clock_getres		= posix_get_hrtimer_res, +	.clock_get		= posix_get_monotonic_raw, +}; + +static const struct k_clock clock_realtime_coarse = { +	.clock_getres		= posix_get_coarse_res, +	.clock_get		= posix_get_realtime_coarse, +}; + +static const struct k_clock clock_monotonic_coarse = { +	.clock_getres		= posix_get_coarse_res, +	.clock_get		= posix_get_monotonic_coarse, +}; + +static const struct k_clock clock_tai = { +	.clock_getres		= posix_get_hrtimer_res, +	.clock_get		= posix_get_tai, +	.nsleep			= common_nsleep, +	.timer_create		= common_timer_create, +	.timer_set		= common_timer_set, +	.timer_get		= common_timer_get, +	.timer_del		= common_timer_del, +	.timer_rearm		= common_hrtimer_rearm, +	.timer_forward		= common_hrtimer_forward, +	.timer_remaining	= common_hrtimer_remaining, +	.timer_try_to_cancel	= common_hrtimer_try_to_cancel, +	.timer_arm		= common_hrtimer_arm, +}; + +static const struct k_clock clock_boottime = { +	.clock_getres		= posix_get_hrtimer_res, +	.clock_get		= posix_get_boottime, +	.nsleep			= common_nsleep, +	.timer_create		= common_timer_create, +	.timer_set		= common_timer_set, +	.timer_get		= common_timer_get, +	.timer_del		= common_timer_del, +	.timer_rearm		= common_hrtimer_rearm, +	.timer_forward		= common_hrtimer_forward, +	.timer_remaining	= common_hrtimer_remaining, +	.timer_try_to_cancel	= common_hrtimer_try_to_cancel, +	.timer_arm		= common_hrtimer_arm, +}; + +static const struct k_clock * const posix_clocks[] = { +	[CLOCK_REALTIME]		= &clock_realtime, +	[CLOCK_MONOTONIC]		= &clock_monotonic, +	[CLOCK_PROCESS_CPUTIME_ID]	= &clock_process, +	[CLOCK_THREAD_CPUTIME_ID]	= &clock_thread, +	[CLOCK_MONOTONIC_RAW]		= &clock_monotonic_raw, +	[CLOCK_REALTIME_COARSE]		= &clock_realtime_coarse, +	[CLOCK_MONOTONIC_COARSE]	= &clock_monotonic_coarse, +	[CLOCK_BOOTTIME]		= &clock_boottime, +	[CLOCK_REALTIME_ALARM]		= &alarm_clock, +	[CLOCK_BOOTTIME_ALARM]		= &alarm_clock, +	[CLOCK_TAI]			= &clock_tai, +}; + +static const struct k_clock *clockid_to_kclock(const clockid_t id) +{ +	if (id < 0) +		return (id & CLOCKFD_MASK) == CLOCKFD ? +			&clock_posix_dynamic : &clock_posix_cpu; + +	if (id >= ARRAY_SIZE(posix_clocks) || !posix_clocks[id]) +		return NULL; +	return posix_clocks[id];  } diff --git a/kernel/time/posix-timers.h b/kernel/time/posix-timers.h new file mode 100644 index 000000000000..fb303c3be4d3 --- /dev/null +++ b/kernel/time/posix-timers.h @@ -0,0 +1,40 @@ +#define TIMER_RETRY 1 + +struct k_clock { +	int	(*clock_getres)(const clockid_t which_clock, +				struct timespec64 *tp); +	int	(*clock_set)(const clockid_t which_clock, +			     const struct timespec64 *tp); +	int	(*clock_get)(const clockid_t which_clock, +			     struct timespec64 *tp); +	int	(*clock_adj)(const clockid_t which_clock, struct timex *tx); +	int	(*timer_create)(struct k_itimer *timer); +	int	(*nsleep)(const clockid_t which_clock, int flags, +			  const struct timespec64 *); +	int	(*timer_set)(struct k_itimer *timr, int flags, +			     struct itimerspec64 *new_setting, +			     struct itimerspec64 *old_setting); +	int	(*timer_del)(struct k_itimer *timr); +	void	(*timer_get)(struct k_itimer *timr, +			     struct itimerspec64 *cur_setting); +	void	(*timer_rearm)(struct k_itimer *timr); +	int	(*timer_forward)(struct k_itimer *timr, ktime_t now); +	ktime_t	(*timer_remaining)(struct k_itimer *timr, ktime_t now); +	int	(*timer_try_to_cancel)(struct k_itimer *timr); +	void	(*timer_arm)(struct k_itimer *timr, ktime_t expires, +			     bool absolute, bool sigev_none); +}; + +extern const struct k_clock clock_posix_cpu; +extern const struct k_clock clock_posix_dynamic; +extern const struct k_clock clock_process; +extern const struct k_clock clock_thread; +extern const struct k_clock alarm_clock; + +int posix_timer_event(struct k_itimer *timr, int si_private); + +void common_timer_get(struct k_itimer *timr, struct itimerspec64 *cur_setting); +int common_timer_set(struct k_itimer *timr, int flags, +		     struct itimerspec64 *new_setting, +		     struct itimerspec64 *old_setting); +int common_timer_del(struct k_itimer *timer); diff --git a/kernel/time/time.c b/kernel/time/time.c index 49c73c6ed648..7c89e437c4d7 100644 --- a/kernel/time/time.c +++ b/kernel/time/time.c @@ -39,6 +39,7 @@  #include <linux/ptrace.h>  #include <linux/uaccess.h> +#include <linux/compat.h>  #include <asm/unistd.h>  #include <generated/timeconst.h> @@ -99,6 +100,47 @@ SYSCALL_DEFINE1(stime, time_t __user *, tptr)  #endif /* __ARCH_WANT_SYS_TIME */ +#ifdef CONFIG_COMPAT +#ifdef __ARCH_WANT_COMPAT_SYS_TIME + +/* compat_time_t is a 32 bit "long" and needs to get converted. */ +COMPAT_SYSCALL_DEFINE1(time, compat_time_t __user *, tloc) +{ +	struct timeval tv; +	compat_time_t i; + +	do_gettimeofday(&tv); +	i = tv.tv_sec; + +	if (tloc) { +		if (put_user(i,tloc)) +			return -EFAULT; +	} +	force_successful_syscall_return(); +	return i; +} + +COMPAT_SYSCALL_DEFINE1(stime, compat_time_t __user *, tptr) +{ +	struct timespec tv; +	int err; + +	if (get_user(tv.tv_sec, tptr)) +		return -EFAULT; + +	tv.tv_nsec = 0; + +	err = security_settime(&tv, NULL); +	if (err) +		return err; + +	do_settimeofday(&tv); +	return 0; +} + +#endif /* __ARCH_WANT_COMPAT_SYS_TIME */ +#endif +  SYSCALL_DEFINE2(gettimeofday, struct timeval __user *, tv,  		struct timezone __user *, tz)  { @@ -215,6 +257,47 @@ SYSCALL_DEFINE2(settimeofday, struct timeval __user *, tv,  	return do_sys_settimeofday64(tv ? &new_ts : NULL, tz ? &new_tz : NULL);  } +#ifdef CONFIG_COMPAT +COMPAT_SYSCALL_DEFINE2(gettimeofday, struct compat_timeval __user *, tv, +		       struct timezone __user *, tz) +{ +	if (tv) { +		struct timeval ktv; + +		do_gettimeofday(&ktv); +		if (compat_put_timeval(&ktv, tv)) +			return -EFAULT; +	} +	if (tz) { +		if (copy_to_user(tz, &sys_tz, sizeof(sys_tz))) +			return -EFAULT; +	} + +	return 0; +} + +COMPAT_SYSCALL_DEFINE2(settimeofday, struct compat_timeval __user *, tv, +		       struct timezone __user *, tz) +{ +	struct timespec64 new_ts; +	struct timeval user_tv; +	struct timezone new_tz; + +	if (tv) { +		if (compat_get_timeval(&user_tv, tv)) +			return -EFAULT; +		new_ts.tv_sec = user_tv.tv_sec; +		new_ts.tv_nsec = user_tv.tv_usec * NSEC_PER_USEC; +	} +	if (tz) { +		if (copy_from_user(&new_tz, tz, sizeof(*tz))) +			return -EFAULT; +	} + +	return do_sys_settimeofday64(tv ? &new_ts : NULL, tz ? &new_tz : NULL); +} +#endif +  SYSCALL_DEFINE1(adjtimex, struct timex __user *, txc_p)  {  	struct timex txc;		/* Local copy of parameter */ @@ -224,12 +307,33 @@ SYSCALL_DEFINE1(adjtimex, struct timex __user *, txc_p)  	 * structure. But bear in mind that the structures  	 * may change  	 */ -	if(copy_from_user(&txc, txc_p, sizeof(struct timex))) +	if (copy_from_user(&txc, txc_p, sizeof(struct timex)))  		return -EFAULT;  	ret = do_adjtimex(&txc);  	return copy_to_user(txc_p, &txc, sizeof(struct timex)) ? -EFAULT : ret;  } +#ifdef CONFIG_COMPAT + +COMPAT_SYSCALL_DEFINE1(adjtimex, struct compat_timex __user *, utp) +{ +	struct timex txc; +	int err, ret; + +	err = compat_get_timex(&txc, utp); +	if (err) +		return err; + +	ret = do_adjtimex(&txc); + +	err = compat_put_timex(utp, &txc); +	if (err) +		return err; + +	return ret; +} +#endif +  /*   * Convert jiffies to milliseconds and back.   * diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index b602c48cb841..cedafa008de5 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -72,6 +72,10 @@ static inline void tk_normalize_xtime(struct timekeeper *tk)  		tk->tkr_mono.xtime_nsec -= (u64)NSEC_PER_SEC << tk->tkr_mono.shift;  		tk->xtime_sec++;  	} +	while (tk->tkr_raw.xtime_nsec >= ((u64)NSEC_PER_SEC << tk->tkr_raw.shift)) { +		tk->tkr_raw.xtime_nsec -= (u64)NSEC_PER_SEC << tk->tkr_raw.shift; +		tk->raw_sec++; +	}  }  static inline struct timespec64 tk_xtime(struct timekeeper *tk) @@ -285,12 +289,14 @@ static void tk_setup_internals(struct timekeeper *tk, struct clocksource *clock)  	 /* if changing clocks, convert xtime_nsec shift units */  	if (old_clock) {  		int shift_change = clock->shift - old_clock->shift; -		if (shift_change < 0) +		if (shift_change < 0) {  			tk->tkr_mono.xtime_nsec >>= -shift_change; -		else +			tk->tkr_raw.xtime_nsec >>= -shift_change; +		} else {  			tk->tkr_mono.xtime_nsec <<= shift_change; +			tk->tkr_raw.xtime_nsec <<= shift_change; +		}  	} -	tk->tkr_raw.xtime_nsec = 0;  	tk->tkr_mono.shift = clock->shift;  	tk->tkr_raw.shift = clock->shift; @@ -510,6 +516,7 @@ static void halt_fast_timekeeper(struct timekeeper *tk)  }  #ifdef CONFIG_GENERIC_TIME_VSYSCALL_OLD +#warning Please contact your maintainers, as GENERIC_TIME_VSYSCALL_OLD compatibity will disappear soon.  static inline void update_vsyscall(struct timekeeper *tk)  { @@ -619,9 +626,6 @@ static inline void tk_update_ktime_data(struct timekeeper *tk)  	nsec = (u32) tk->wall_to_monotonic.tv_nsec;  	tk->tkr_mono.base = ns_to_ktime(seconds * NSEC_PER_SEC + nsec); -	/* Update the monotonic raw base */ -	tk->tkr_raw.base = timespec64_to_ktime(tk->raw_time); -  	/*  	 * The sum of the nanoseconds portions of xtime and  	 * wall_to_monotonic can be greater/equal one second. Take @@ -631,6 +635,11 @@ static inline void tk_update_ktime_data(struct timekeeper *tk)  	if (nsec >= NSEC_PER_SEC)  		seconds++;  	tk->ktime_sec = seconds; + +	/* Update the monotonic raw base */ +	seconds = tk->raw_sec; +	nsec = (u32)(tk->tkr_raw.xtime_nsec >> tk->tkr_raw.shift); +	tk->tkr_raw.base = ns_to_ktime(seconds * NSEC_PER_SEC + nsec);  }  /* must hold timekeeper_lock */ @@ -672,7 +681,6 @@ static void timekeeping_update(struct timekeeper *tk, unsigned int action)  static void timekeeping_forward_now(struct timekeeper *tk)  {  	u64 cycle_now, delta; -	u64 nsec;  	cycle_now = tk_clock_read(&tk->tkr_mono);  	delta = clocksource_delta(cycle_now, tk->tkr_mono.cycle_last, tk->tkr_mono.mask); @@ -684,10 +692,13 @@ static void timekeeping_forward_now(struct timekeeper *tk)  	/* If arch requires, add in get_arch_timeoffset() */  	tk->tkr_mono.xtime_nsec += (u64)arch_gettimeoffset() << tk->tkr_mono.shift; -	tk_normalize_xtime(tk); -	nsec = clocksource_cyc2ns(delta, tk->tkr_raw.mult, tk->tkr_raw.shift); -	timespec64_add_ns(&tk->raw_time, nsec); +	tk->tkr_raw.xtime_nsec += delta * tk->tkr_raw.mult; + +	/* If arch requires, add in get_arch_timeoffset() */ +	tk->tkr_raw.xtime_nsec += (u64)arch_gettimeoffset() << tk->tkr_raw.shift; + +	tk_normalize_xtime(tk);  }  /** @@ -1373,19 +1384,18 @@ int timekeeping_notify(struct clocksource *clock)  void getrawmonotonic64(struct timespec64 *ts)  {  	struct timekeeper *tk = &tk_core.timekeeper; -	struct timespec64 ts64;  	unsigned long seq;  	u64 nsecs;  	do {  		seq = read_seqcount_begin(&tk_core.seq); +		ts->tv_sec = tk->raw_sec;  		nsecs = timekeeping_get_ns(&tk->tkr_raw); -		ts64 = tk->raw_time;  	} while (read_seqcount_retry(&tk_core.seq, seq)); -	timespec64_add_ns(&ts64, nsecs); -	*ts = ts64; +	ts->tv_nsec = 0; +	timespec64_add_ns(ts, nsecs);  }  EXPORT_SYMBOL(getrawmonotonic64); @@ -1509,8 +1519,7 @@ void __init timekeeping_init(void)  	tk_setup_internals(tk, clock);  	tk_set_xtime(tk, &now); -	tk->raw_time.tv_sec = 0; -	tk->raw_time.tv_nsec = 0; +	tk->raw_sec = 0;  	if (boot.tv_sec == 0 && boot.tv_nsec == 0)  		boot = tk_xtime(tk); @@ -2011,15 +2020,12 @@ static u64 logarithmic_accumulation(struct timekeeper *tk, u64 offset,  	*clock_set |= accumulate_nsecs_to_secs(tk);  	/* Accumulate raw time */ -	tk->tkr_raw.xtime_nsec += (u64)tk->raw_time.tv_nsec << tk->tkr_raw.shift;  	tk->tkr_raw.xtime_nsec += tk->raw_interval << shift;  	snsec_per_sec = (u64)NSEC_PER_SEC << tk->tkr_raw.shift;  	while (tk->tkr_raw.xtime_nsec >= snsec_per_sec) {  		tk->tkr_raw.xtime_nsec -= snsec_per_sec; -		tk->raw_time.tv_sec++; +		tk->raw_sec++;  	} -	tk->raw_time.tv_nsec = tk->tkr_raw.xtime_nsec >> tk->tkr_raw.shift; -	tk->tkr_raw.xtime_nsec -= (u64)tk->raw_time.tv_nsec << tk->tkr_raw.shift;  	/* Accumulate error between NTP and clock interval */  	tk->ntp_error += tk->ntp_tick << shift; diff --git a/kernel/time/timer.c b/kernel/time/timer.c index 152a706ef8b8..71ce3f4eead3 100644 --- a/kernel/time/timer.c +++ b/kernel/time/timer.c @@ -195,7 +195,7 @@ EXPORT_SYMBOL(jiffies_64);  #endif  struct timer_base { -	spinlock_t		lock; +	raw_spinlock_t		lock;  	struct timer_list	*running_timer;  	unsigned long		clk;  	unsigned long		next_expiry; @@ -913,10 +913,10 @@ static struct timer_base *lock_timer_base(struct timer_list *timer,  		if (!(tf & TIMER_MIGRATING)) {  			base = get_timer_base(tf); -			spin_lock_irqsave(&base->lock, *flags); +			raw_spin_lock_irqsave(&base->lock, *flags);  			if (timer->flags == tf)  				return base; -			spin_unlock_irqrestore(&base->lock, *flags); +			raw_spin_unlock_irqrestore(&base->lock, *flags);  		}  		cpu_relax();  	} @@ -986,9 +986,9 @@ __mod_timer(struct timer_list *timer, unsigned long expires, bool pending_only)  			/* See the comment in lock_timer_base() */  			timer->flags |= TIMER_MIGRATING; -			spin_unlock(&base->lock); +			raw_spin_unlock(&base->lock);  			base = new_base; -			spin_lock(&base->lock); +			raw_spin_lock(&base->lock);  			WRITE_ONCE(timer->flags,  				   (timer->flags & ~TIMER_BASEMASK) | base->cpu);  		} @@ -1013,7 +1013,7 @@ __mod_timer(struct timer_list *timer, unsigned long expires, bool pending_only)  	}  out_unlock: -	spin_unlock_irqrestore(&base->lock, flags); +	raw_spin_unlock_irqrestore(&base->lock, flags);  	return ret;  } @@ -1106,16 +1106,16 @@ void add_timer_on(struct timer_list *timer, int cpu)  	if (base != new_base) {  		timer->flags |= TIMER_MIGRATING; -		spin_unlock(&base->lock); +		raw_spin_unlock(&base->lock);  		base = new_base; -		spin_lock(&base->lock); +		raw_spin_lock(&base->lock);  		WRITE_ONCE(timer->flags,  			   (timer->flags & ~TIMER_BASEMASK) | cpu);  	}  	debug_activate(timer, timer->expires);  	internal_add_timer(base, timer); -	spin_unlock_irqrestore(&base->lock, flags); +	raw_spin_unlock_irqrestore(&base->lock, flags);  }  EXPORT_SYMBOL_GPL(add_timer_on); @@ -1141,7 +1141,7 @@ int del_timer(struct timer_list *timer)  	if (timer_pending(timer)) {  		base = lock_timer_base(timer, &flags);  		ret = detach_if_pending(timer, base, true); -		spin_unlock_irqrestore(&base->lock, flags); +		raw_spin_unlock_irqrestore(&base->lock, flags);  	}  	return ret; @@ -1150,7 +1150,7 @@ EXPORT_SYMBOL(del_timer);  /**   * try_to_del_timer_sync - Try to deactivate a timer - * @timer: timer do del + * @timer: timer to delete   *   * This function tries to deactivate a timer. Upon successful (ret >= 0)   * exit the timer is not queued and the handler is not running on any CPU. @@ -1168,7 +1168,7 @@ int try_to_del_timer_sync(struct timer_list *timer)  	if (base->running_timer != timer)  		ret = detach_if_pending(timer, base, true); -	spin_unlock_irqrestore(&base->lock, flags); +	raw_spin_unlock_irqrestore(&base->lock, flags);  	return ret;  } @@ -1299,13 +1299,13 @@ static void expire_timers(struct timer_base *base, struct hlist_head *head)  		data = timer->data;  		if (timer->flags & TIMER_IRQSAFE) { -			spin_unlock(&base->lock); +			raw_spin_unlock(&base->lock);  			call_timer_fn(timer, fn, data); -			spin_lock(&base->lock); +			raw_spin_lock(&base->lock);  		} else { -			spin_unlock_irq(&base->lock); +			raw_spin_unlock_irq(&base->lock);  			call_timer_fn(timer, fn, data); -			spin_lock_irq(&base->lock); +			raw_spin_lock_irq(&base->lock);  		}  	}  } @@ -1474,7 +1474,7 @@ u64 get_next_timer_interrupt(unsigned long basej, u64 basem)  	if (cpu_is_offline(smp_processor_id()))  		return expires; -	spin_lock(&base->lock); +	raw_spin_lock(&base->lock);  	nextevt = __next_timer_interrupt(base);  	is_max_delta = (nextevt == base->clk + NEXT_TIMER_MAX_DELTA);  	base->next_expiry = nextevt; @@ -1502,7 +1502,7 @@ u64 get_next_timer_interrupt(unsigned long basej, u64 basem)  		if ((expires - basem) > TICK_NSEC)  			base->is_idle = true;  	} -	spin_unlock(&base->lock); +	raw_spin_unlock(&base->lock);  	return cmp_next_hrtimer_event(basem, expires);  } @@ -1590,7 +1590,7 @@ static inline void __run_timers(struct timer_base *base)  	if (!time_after_eq(jiffies, base->clk))  		return; -	spin_lock_irq(&base->lock); +	raw_spin_lock_irq(&base->lock);  	while (time_after_eq(jiffies, base->clk)) { @@ -1601,7 +1601,7 @@ static inline void __run_timers(struct timer_base *base)  			expire_timers(base, heads + levels);  	}  	base->running_timer = NULL; -	spin_unlock_irq(&base->lock); +	raw_spin_unlock_irq(&base->lock);  }  /* @@ -1786,16 +1786,16 @@ int timers_dead_cpu(unsigned int cpu)  		 * The caller is globally serialized and nobody else  		 * takes two locks at once, deadlock is not possible.  		 */ -		spin_lock_irq(&new_base->lock); -		spin_lock_nested(&old_base->lock, SINGLE_DEPTH_NESTING); +		raw_spin_lock_irq(&new_base->lock); +		raw_spin_lock_nested(&old_base->lock, SINGLE_DEPTH_NESTING);  		BUG_ON(old_base->running_timer);  		for (i = 0; i < WHEEL_SIZE; i++)  			migrate_timer_list(new_base, old_base->vectors + i); -		spin_unlock(&old_base->lock); -		spin_unlock_irq(&new_base->lock); +		raw_spin_unlock(&old_base->lock); +		raw_spin_unlock_irq(&new_base->lock);  		put_cpu_ptr(&timer_bases);  	}  	return 0; @@ -1811,7 +1811,7 @@ static void __init init_timer_cpu(int cpu)  	for (i = 0; i < NR_BASES; i++) {  		base = per_cpu_ptr(&timer_bases[i], cpu);  		base->cpu = cpu; -		spin_lock_init(&base->lock); +		raw_spin_lock_init(&base->lock);  		base->clk = jiffies;  	}  } diff --git a/tools/testing/selftests/timers/Makefile b/tools/testing/selftests/timers/Makefile index 5fa1d7e9a915..5801bbefbe89 100644 --- a/tools/testing/selftests/timers/Makefile +++ b/tools/testing/selftests/timers/Makefile @@ -1,6 +1,6 @@  BUILD_FLAGS = -DKTEST  CFLAGS += -O3 -Wl,-no-as-needed -Wall $(BUILD_FLAGS) -LDFLAGS += -lrt -lpthread +LDFLAGS += -lrt -lpthread -lm  # these are all "safe" tests that don't modify  # system time or require escalated privileges @@ -8,7 +8,7 @@ TEST_GEN_PROGS = posix_timers nanosleep nsleep-lat set-timer-lat mqueue-lat \  	     inconsistency-check raw_skew threadtest rtctest  TEST_GEN_PROGS_EXTENDED = alarmtimer-suspend valid-adjtimex adjtick change_skew \ -		      skew_consistency clocksource-switch leap-a-day \ +		      skew_consistency clocksource-switch freq-step leap-a-day \  		      leapcrash set-tai set-2038 set-tz @@ -24,6 +24,7 @@ run_destructive_tests: run_tests  	./change_skew  	./skew_consistency  	./clocksource-switch +	./freq-step  	./leap-a-day -s -i 10  	./leapcrash  	./set-tz diff --git a/tools/testing/selftests/timers/freq-step.c b/tools/testing/selftests/timers/freq-step.c new file mode 100644 index 000000000000..e8c61830825a --- /dev/null +++ b/tools/testing/selftests/timers/freq-step.c @@ -0,0 +1,268 @@ +/* + * This test checks the response of the system clock to frequency + * steps made with adjtimex(). The frequency error and stability of + * the CLOCK_MONOTONIC clock relative to the CLOCK_MONOTONIC_RAW clock + * is measured in two intervals following the step. The test fails if + * values from the second interval exceed specified limits. + * + * Copyright (C) Miroslav Lichvar <[email protected]>  2017 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + */ + +#include <math.h> +#include <stdio.h> +#include <sys/timex.h> +#include <time.h> +#include <unistd.h> + +#include "../kselftest.h" + +#define SAMPLES 100 +#define SAMPLE_READINGS 10 +#define MEAN_SAMPLE_INTERVAL 0.1 +#define STEP_INTERVAL 1.0 +#define MAX_PRECISION 100e-9 +#define MAX_FREQ_ERROR 10e-6 +#define MAX_STDDEV 1000e-9 + +struct sample { +	double offset; +	double time; +}; + +static time_t mono_raw_base; +static time_t mono_base; +static long user_hz; +static double precision; +static double mono_freq_offset; + +static double diff_timespec(struct timespec *ts1, struct timespec *ts2) +{ +	return ts1->tv_sec - ts2->tv_sec + (ts1->tv_nsec - ts2->tv_nsec) / 1e9; +} + +static double get_sample(struct sample *sample) +{ +	double delay, mindelay = 0.0; +	struct timespec ts1, ts2, ts3; +	int i; + +	for (i = 0; i < SAMPLE_READINGS; i++) { +		clock_gettime(CLOCK_MONOTONIC_RAW, &ts1); +		clock_gettime(CLOCK_MONOTONIC, &ts2); +		clock_gettime(CLOCK_MONOTONIC_RAW, &ts3); + +		ts1.tv_sec -= mono_raw_base; +		ts2.tv_sec -= mono_base; +		ts3.tv_sec -= mono_raw_base; + +		delay = diff_timespec(&ts3, &ts1); +		if (delay <= 1e-9) { +			i--; +			continue; +		} + +		if (!i || delay < mindelay) { +			sample->offset = diff_timespec(&ts2, &ts1); +			sample->offset -= delay / 2.0; +			sample->time = ts1.tv_sec + ts1.tv_nsec / 1e9; +			mindelay = delay; +		} +	} + +	return mindelay; +} + +static void reset_ntp_error(void) +{ +	struct timex txc; + +	txc.modes = ADJ_SETOFFSET; +	txc.time.tv_sec = 0; +	txc.time.tv_usec = 0; + +	if (adjtimex(&txc) < 0) { +		perror("[FAIL] adjtimex"); +		ksft_exit_fail(); +	} +} + +static void set_frequency(double freq) +{ +	struct timex txc; +	int tick_offset; + +	tick_offset = 1e6 * freq / user_hz; + +	txc.modes = ADJ_TICK | ADJ_FREQUENCY; +	txc.tick = 1000000 / user_hz + tick_offset; +	txc.freq = (1e6 * freq - user_hz * tick_offset) * (1 << 16); + +	if (adjtimex(&txc) < 0) { +		perror("[FAIL] adjtimex"); +		ksft_exit_fail(); +	} +} + +static void regress(struct sample *samples, int n, double *intercept, +		    double *slope, double *r_stddev, double *r_max) +{ +	double x, y, r, x_sum, y_sum, xy_sum, x2_sum, r2_sum; +	int i; + +	x_sum = 0.0, y_sum = 0.0, xy_sum = 0.0, x2_sum = 0.0; + +	for (i = 0; i < n; i++) { +		x = samples[i].time; +		y = samples[i].offset; + +		x_sum += x; +		y_sum += y; +		xy_sum += x * y; +		x2_sum += x * x; +	} + +	*slope = (xy_sum - x_sum * y_sum / n) / (x2_sum - x_sum * x_sum / n); +	*intercept = (y_sum - *slope * x_sum) / n; + +	*r_max = 0.0, r2_sum = 0.0; + +	for (i = 0; i < n; i++) { +		x = samples[i].time; +		y = samples[i].offset; +		r = fabs(x * *slope + *intercept - y); +		if (*r_max < r) +			*r_max = r; +		r2_sum += r * r; +	} + +	*r_stddev = sqrt(r2_sum / n); +} + +static int run_test(int calibration, double freq_base, double freq_step) +{ +	struct sample samples[SAMPLES]; +	double intercept, slope, stddev1, max1, stddev2, max2; +	double freq_error1, freq_error2; +	int i; + +	set_frequency(freq_base); + +	for (i = 0; i < 10; i++) +		usleep(1e6 * MEAN_SAMPLE_INTERVAL / 10); + +	reset_ntp_error(); + +	set_frequency(freq_base + freq_step); + +	for (i = 0; i < 10; i++) +		usleep(rand() % 2000000 * STEP_INTERVAL / 10); + +	set_frequency(freq_base); + +	for (i = 0; i < SAMPLES; i++) { +		usleep(rand() % 2000000 * MEAN_SAMPLE_INTERVAL); +		get_sample(&samples[i]); +	} + +	if (calibration) { +		regress(samples, SAMPLES, &intercept, &slope, &stddev1, &max1); +		mono_freq_offset = slope; +		printf("CLOCK_MONOTONIC_RAW frequency offset: %11.3f ppm\n", +		       1e6 * mono_freq_offset); +		return 0; +	} + +	regress(samples, SAMPLES / 2, &intercept, &slope, &stddev1, &max1); +	freq_error1 = slope * (1.0 - mono_freq_offset) - mono_freq_offset - +			freq_base; + +	regress(samples + SAMPLES / 2, SAMPLES / 2, &intercept, &slope, +		&stddev2, &max2); +	freq_error2 = slope * (1.0 - mono_freq_offset) - mono_freq_offset - +			freq_base; + +	printf("%6.0f %+10.3f %6.0f %7.0f %+10.3f %6.0f %7.0f\t", +	       1e6 * freq_step, +	       1e6 * freq_error1, 1e9 * stddev1, 1e9 * max1, +	       1e6 * freq_error2, 1e9 * stddev2, 1e9 * max2); + +	if (fabs(freq_error2) > MAX_FREQ_ERROR || stddev2 > MAX_STDDEV) { +		printf("[FAIL]\n"); +		return 1; +	} + +	printf("[OK]\n"); +	return 0; +} + +static void init_test(void) +{ +	struct timespec ts; +	struct sample sample; + +	if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts)) { +		perror("[FAIL] clock_gettime(CLOCK_MONOTONIC_RAW)"); +		ksft_exit_fail(); +	} + +	mono_raw_base = ts.tv_sec; + +	if (clock_gettime(CLOCK_MONOTONIC, &ts)) { +		perror("[FAIL] clock_gettime(CLOCK_MONOTONIC)"); +		ksft_exit_fail(); +	} + +	mono_base = ts.tv_sec; + +	user_hz = sysconf(_SC_CLK_TCK); + +	precision = get_sample(&sample) / 2.0; +	printf("CLOCK_MONOTONIC_RAW+CLOCK_MONOTONIC precision: %.0f ns\t\t", +	       1e9 * precision); + +	if (precision > MAX_PRECISION) { +		printf("[SKIP]\n"); +		ksft_exit_skip(); +	} + +	printf("[OK]\n"); +	srand(ts.tv_sec ^ ts.tv_nsec); + +	run_test(1, 0.0, 0.0); +} + +int main(int argc, char **argv) +{ +	double freq_base, freq_step; +	int i, j, fails = 0; + +	init_test(); + +	printf("Checking response to frequency step:\n"); +	printf("  Step           1st interval              2nd interval\n"); +	printf("             Freq    Dev     Max       Freq    Dev     Max\n"); + +	for (i = 2; i >= 0; i--) { +		for (j = 0; j < 5; j++) { +			freq_base = (rand() % (1 << 24) - (1 << 23)) / 65536e6; +			freq_step = 10e-6 * (1 << (6 * i)); +			fails += run_test(0, freq_base, freq_step); +		} +	} + +	set_frequency(0.0); + +	if (fails) +		ksft_exit_fail(); + +	ksft_exit_pass(); +} diff --git a/tools/testing/selftests/timers/inconsistency-check.c b/tools/testing/selftests/timers/inconsistency-check.c index caf1bc9257c4..74c60e8759a0 100644 --- a/tools/testing/selftests/timers/inconsistency-check.c +++ b/tools/testing/selftests/timers/inconsistency-check.c @@ -118,7 +118,7 @@ int consistency_test(int clock_type, unsigned long seconds)  	start_str = ctime(&t);  	while (seconds == -1 || now - then < seconds) { -		inconsistent = 0; +		inconsistent = -1;  		/* Fill list */  		for (i = 0; i < CALLS_PER_LOOP; i++) @@ -130,7 +130,7 @@ int consistency_test(int clock_type, unsigned long seconds)  				inconsistent = i;  		/* display inconsistency */ -		if (inconsistent) { +		if (inconsistent >= 0) {  			unsigned long long delta;  			printf("\%s\n", start_str); |