Blame view

kernel/time/tick-oneshot.c 3.15 KB
35728b820   Thomas Gleixner   time: Add SPDX li...
1
  // SPDX-License-Identifier: GPL-2.0
79bf2bb33   Thomas Gleixner   [PATCH] tick-mana...
2
  /*
79bf2bb33   Thomas Gleixner   [PATCH] tick-mana...
3
4
5
6
7
8
   * This file contains functions which manage high resolution tick
   * related events.
   *
   * Copyright(C) 2005-2006, Thomas Gleixner <tglx@linutronix.de>
   * Copyright(C) 2005-2007, Red Hat, Inc., Ingo Molnar
   * Copyright(C) 2006-2007, Timesys Corp., Thomas Gleixner
79bf2bb33   Thomas Gleixner   [PATCH] tick-mana...
9
10
11
12
   */
  #include <linux/cpu.h>
  #include <linux/err.h>
  #include <linux/hrtimer.h>
d7b906897   Russell King   [S390] genirq/clo...
13
  #include <linux/interrupt.h>
79bf2bb33   Thomas Gleixner   [PATCH] tick-mana...
14
15
16
  #include <linux/percpu.h>
  #include <linux/profile.h>
  #include <linux/sched.h>
79bf2bb33   Thomas Gleixner   [PATCH] tick-mana...
17
18
  
  #include "tick-internal.h"
79bf2bb33   Thomas Gleixner   [PATCH] tick-mana...
19
  /**
7205656ab   Thomas Gleixner   clockevents: enfo...
20
21
22
23
   * tick_program_event
   */
  int tick_program_event(ktime_t expires, int force)
  {
909ea9646   Christoph Lameter   core: Replace __g...
24
  	struct clock_event_device *dev = __this_cpu_read(tick_cpu_device.evtdev);
7205656ab   Thomas Gleixner   clockevents: enfo...
25

2456e8553   Thomas Gleixner   ktime: Get rid of...
26
  	if (unlikely(expires == KTIME_MAX)) {
d25408756   Viresh Kumar   clockevents: Stop...
27
28
29
  		/*
  		 * We don't need the clock event device any more, stop it.
  		 */
d7eb231c7   Thomas Gleixner   clockevents: Prov...
30
  		clockevents_switch_state(dev, CLOCK_EVT_STATE_ONESHOT_STOPPED);
39c82caff   Prasad Sodagudi   clockevents: Upda...
31
  		dev->next_event = KTIME_MAX;
d25408756   Viresh Kumar   clockevents: Stop...
32
33
  		return 0;
  	}
472c4a943   Viresh Kumar   clockevents: Use ...
34
  	if (unlikely(clockevent_state_oneshot_stopped(dev))) {
d25408756   Viresh Kumar   clockevents: Stop...
35
36
37
38
  		/*
  		 * We need the clock event again, configure it in ONESHOT mode
  		 * before using it.
  		 */
d7eb231c7   Thomas Gleixner   clockevents: Prov...
39
  		clockevents_switch_state(dev, CLOCK_EVT_STATE_ONESHOT);
d25408756   Viresh Kumar   clockevents: Stop...
40
  	}
d1748302f   Martin Schwidefsky   clockevents: Make...
41
  	return clockevents_program_event(dev, expires, force);
7205656ab   Thomas Gleixner   clockevents: enfo...
42
43
44
  }
  
  /**
cd05a1f81   Thomas Gleixner   [PATCH] clockeven...
45
46
47
48
   * tick_resume_onshot - resume oneshot mode
   */
  void tick_resume_oneshot(void)
  {
d1748302f   Martin Schwidefsky   clockevents: Make...
49
  	struct clock_event_device *dev = __this_cpu_read(tick_cpu_device.evtdev);
cd05a1f81   Thomas Gleixner   [PATCH] clockeven...
50

d7eb231c7   Thomas Gleixner   clockevents: Prov...
51
  	clockevents_switch_state(dev, CLOCK_EVT_STATE_ONESHOT);
d1748302f   Martin Schwidefsky   clockevents: Make...
52
  	clockevents_program_event(dev, ktime_get(), true);
cd05a1f81   Thomas Gleixner   [PATCH] clockeven...
53
54
55
  }
  
  /**
79bf2bb33   Thomas Gleixner   [PATCH] tick-mana...
56
57
58
59
60
61
62
   * tick_setup_oneshot - setup the event device for oneshot mode (hres or nohz)
   */
  void tick_setup_oneshot(struct clock_event_device *newdev,
  			void (*handler)(struct clock_event_device *),
  			ktime_t next_event)
  {
  	newdev->event_handler = handler;
d7eb231c7   Thomas Gleixner   clockevents: Prov...
63
  	clockevents_switch_state(newdev, CLOCK_EVT_STATE_ONESHOT);
d1748302f   Martin Schwidefsky   clockevents: Make...
64
  	clockevents_program_event(newdev, next_event, true);
79bf2bb33   Thomas Gleixner   [PATCH] tick-mana...
65
66
67
68
69
70
71
  }
  
  /**
   * tick_switch_to_oneshot - switch to oneshot mode
   */
  int tick_switch_to_oneshot(void (*handler)(struct clock_event_device *))
  {
22127e93c   Christoph Lameter   time: Replace __g...
72
  	struct tick_device *td = this_cpu_ptr(&tick_cpu_device);
79bf2bb33   Thomas Gleixner   [PATCH] tick-mana...
73
74
75
  	struct clock_event_device *dev = td->evtdev;
  
  	if (!dev || !(dev->features & CLOCK_EVT_FEAT_ONESHOT) ||
820de5c39   Ingo Molnar   highres: improve ...
76
  		    !tick_device_is_functional(dev)) {
4450dc0ae   Geert Uytterhoeven   clockevents: Fix ...
77
  		pr_info("Clockevents: could not switch to one-shot mode:");
820de5c39   Ingo Molnar   highres: improve ...
78
  		if (!dev) {
4450dc0ae   Geert Uytterhoeven   clockevents: Fix ...
79
80
  			pr_cont(" no tick device
  ");
820de5c39   Ingo Molnar   highres: improve ...
81
82
  		} else {
  			if (!tick_device_is_functional(dev))
4450dc0ae   Geert Uytterhoeven   clockevents: Fix ...
83
84
  				pr_cont(" %s is not functional.
  ", dev->name);
820de5c39   Ingo Molnar   highres: improve ...
85
  			else
4450dc0ae   Geert Uytterhoeven   clockevents: Fix ...
86
87
88
  				pr_cont(" %s does not support one-shot mode.
  ",
  					dev->name);
820de5c39   Ingo Molnar   highres: improve ...
89
  		}
79bf2bb33   Thomas Gleixner   [PATCH] tick-mana...
90
  		return -EINVAL;
820de5c39   Ingo Molnar   highres: improve ...
91
  	}
79bf2bb33   Thomas Gleixner   [PATCH] tick-mana...
92
93
94
  
  	td->mode = TICKDEV_MODE_ONESHOT;
  	dev->event_handler = handler;
d7eb231c7   Thomas Gleixner   clockevents: Prov...
95
  	clockevents_switch_state(dev, CLOCK_EVT_STATE_ONESHOT);
79bf2bb33   Thomas Gleixner   [PATCH] tick-mana...
96
97
98
  	tick_broadcast_switch_to_oneshot();
  	return 0;
  }
cd6d95d84   Thomas Gleixner   clocksource: prev...
99
100
101
102
103
104
105
106
107
108
109
  /**
   * tick_check_oneshot_mode - check whether the system is in oneshot mode
   *
   * returns 1 when either nohz or highres are enabled. otherwise 0.
   */
  int tick_oneshot_mode_active(void)
  {
  	unsigned long flags;
  	int ret;
  
  	local_irq_save(flags);
909ea9646   Christoph Lameter   core: Replace __g...
110
  	ret = __this_cpu_read(tick_cpu_device.mode) == TICKDEV_MODE_ONESHOT;
cd6d95d84   Thomas Gleixner   clocksource: prev...
111
112
113
114
  	local_irq_restore(flags);
  
  	return ret;
  }
79bf2bb33   Thomas Gleixner   [PATCH] tick-mana...
115
116
117
118
119
120
121
122
123
124
125
  #ifdef CONFIG_HIGH_RES_TIMERS
  /**
   * tick_init_highres - switch to high resolution mode
   *
   * Called with interrupts disabled.
   */
  int tick_init_highres(void)
  {
  	return tick_switch_to_oneshot(hrtimer_interrupt);
  }
  #endif