Branch data Line data Source code
1 : : // SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
2 : : /*
3 : : * run something, but later.
4 : : *
5 : : * Timers are run when the SBE timer interrupt triggers (based on us setting
6 : : * it) or when the regular heartbeat call from the OS occurs and there's a
7 : : * timer that's expired.
8 : : *
9 : : * Copyright 2014-2019 IBM Corp.
10 : : */
11 : :
12 : : #include <timer.h>
13 : : #include <timebase.h>
14 : : #include <lock.h>
15 : : #include <fsp.h>
16 : : #include <device.h>
17 : : #include <opal.h>
18 : : #include <sbe.h>
19 : :
20 : : #ifdef __TEST__
21 : : #define this_cpu() ((void *)-1)
22 : : #define cpu_relax()
23 : : static bool running_timer;
24 : : #else
25 : : #include <cpu.h>
26 : : #endif
27 : :
28 : : /* Heartbeat requested from Linux */
29 : : #define HEARTBEAT_DEFAULT_MS 200
30 : :
31 : : static struct lock timer_lock = LOCK_UNLOCKED;
32 : : static LIST_HEAD(timer_list);
33 : : static LIST_HEAD(timer_poll_list);
34 : : static bool timer_in_poll;
35 : : static uint64_t timer_poll_gen;
36 : :
37 : 100 : static inline bool this_cpu_is_running_timer(void)
38 : : {
39 : : #ifdef __TEST__
40 : 100 : return running_timer;
41 : : #else
42 : : return this_cpu()->running_timer;
43 : : #endif
44 : : }
45 : :
46 : 200 : static inline void this_cpu_set_running_timer(bool running)
47 : : {
48 : : #ifdef __TEST__
49 : 200 : running_timer = running;
50 : : #else
51 : : this_cpu()->running_timer = running;
52 : : #endif
53 : 200 : }
54 : :
55 : 65470 : static inline void update_timer_expiry(uint64_t target)
56 : : {
57 : 65470 : if (sbe_timer_present())
58 : 65470 : sbe_update_timer_expiry(target);
59 : 65470 : }
60 : :
61 : 100 : void init_timer(struct timer *t, timer_func_t expiry, void *data)
62 : : {
63 : 100 : t->link.next = t->link.prev = NULL;
64 : 100 : t->target = 0;
65 : 100 : t->expiry = expiry;
66 : 100 : t->user_data = data;
67 : 100 : t->running = NULL;
68 : 100 : }
69 : :
70 : 100 : static void __remove_timer(struct timer *t)
71 : : {
72 : 100 : list_del(&t->link);
73 : 100 : t->link.next = t->link.prev = NULL;
74 : 100 : }
75 : :
76 : 0 : static void __sync_timer(struct timer *t)
77 : : {
78 : : sync();
79 : :
80 : : /* Guard against re-entrancy */
81 : 0 : assert(t->running != this_cpu());
82 : :
83 : 0 : while (t->running) {
84 : 0 : unlock(&timer_lock);
85 : : smt_lowest();
86 : 0 : while (t->running)
87 : 0 : barrier();
88 : : smt_medium();
89 : : /* Should we call the pollers here ? */
90 : 0 : lock(&timer_lock);
91 : : }
92 : 0 : }
93 : :
94 : 0 : void sync_timer(struct timer *t)
95 : : {
96 : 0 : lock(&timer_lock);
97 : 0 : __sync_timer(t);
98 : 0 : unlock(&timer_lock);
99 : 0 : }
100 : :
101 : 0 : void cancel_timer(struct timer *t)
102 : : {
103 : 0 : lock(&timer_lock);
104 : 0 : __sync_timer(t);
105 : 0 : if (t->link.next)
106 : 0 : __remove_timer(t);
107 : 0 : unlock(&timer_lock);
108 : 0 : }
109 : :
110 : 0 : void cancel_timer_async(struct timer *t)
111 : : {
112 : 0 : lock(&timer_lock);
113 : 0 : if (t->link.next)
114 : 0 : __remove_timer(t);
115 : 0 : unlock(&timer_lock);
116 : 0 : }
117 : :
118 : 100 : static void __schedule_timer_at(struct timer *t, uint64_t when)
119 : : {
120 : : struct timer *lt;
121 : :
122 : : /* If the timer is already scheduled, take it out */
123 : 100 : if (t->link.next)
124 : 0 : __remove_timer(t);
125 : :
126 : : /* Update target */
127 : 100 : t->target = when;
128 : :
129 : 100 : if (when == TIMER_POLL) {
130 : : /* It's a poller, add it to the poller list */
131 : 0 : t->gen = timer_poll_gen;
132 : 0 : list_add_tail(&timer_poll_list, &t->link);
133 : : } else {
134 : : /* It's a real timer, add it in the right spot in the
135 : : * ordered timer list
136 : : */
137 : 2761 : list_for_each(&timer_list, lt, link) {
138 : 2757 : if (when >= lt->target)
139 : 2661 : continue;
140 : 96 : list_add_before(&timer_list, <->link, &t->link);
141 : 96 : goto added;
142 : : }
143 : 4 : list_add_tail(&timer_list, &t->link);
144 : 100 : added:
145 : : /* Timer running code will update expiry at the end */
146 : 100 : if (!this_cpu_is_running_timer()) {
147 : : /* Pick the next timer and upddate the SBE HW timer */
148 : 100 : lt = list_top(&timer_list, struct timer, link);
149 : 100 : if (lt && (lt == t || when < lt->target))
150 : 5 : update_timer_expiry(lt->target);
151 : : }
152 : : }
153 : 100 : }
154 : :
155 : 100 : void schedule_timer_at(struct timer *t, uint64_t when)
156 : : {
157 : 100 : lock(&timer_lock);
158 : 100 : __schedule_timer_at(t, when);
159 : 100 : unlock(&timer_lock);
160 : 100 : }
161 : :
162 : 100 : uint64_t schedule_timer(struct timer *t, uint64_t how_long)
163 : : {
164 : 100 : uint64_t now = mftb();
165 : :
166 : 100 : if (how_long == TIMER_POLL)
167 : 0 : schedule_timer_at(t, TIMER_POLL);
168 : : else
169 : 100 : schedule_timer_at(t, now + how_long);
170 : :
171 : 100 : return now;
172 : : }
173 : :
174 : 65466 : static void __check_poll_timers(uint64_t now)
175 : : {
176 : : struct timer *t;
177 : :
178 : : /* Don't call this from multiple CPUs at once */
179 : 65466 : if (timer_in_poll)
180 : 0 : return;
181 : 65466 : timer_in_poll = true;
182 : :
183 : : /*
184 : : * Poll timers might re-enqueue themselves and don't have an
185 : : * expiry so we can't do like normal timers and just run until
186 : : * we hit a wall. Instead, each timer has a generation count,
187 : : * which we set to the current global gen count when we schedule
188 : : * it and update when we run it. It will only be considered if
189 : : * the generation count is different than the current one. We
190 : : * don't try to compare generations being larger or smaller
191 : : * because at boot, this can be called quite quickly and I want
192 : : * to be safe vs. wraps.
193 : : */
194 : 65466 : timer_poll_gen++;
195 : : for (;;) {
196 : 65466 : t = list_top(&timer_poll_list, struct timer, link);
197 : :
198 : : /* Top timer has a different generation than current ? Must
199 : : * be older, we are done.
200 : : */
201 : 65466 : if (!t || t->gen == timer_poll_gen)
202 : : break;
203 : :
204 : : /* Top of list still running, we have to delay handling it,
205 : : * let's reprogram the SLW with a small delay. We chose
206 : : * arbitrarily 1us.
207 : : */
208 : 0 : if (t->running) {
209 : 0 : update_timer_expiry(now + usecs_to_tb(1));
210 : 0 : break;
211 : : }
212 : :
213 : : /* Allright, first remove it and mark it running */
214 : 0 : __remove_timer(t);
215 : 0 : t->running = this_cpu();
216 : 0 : this_cpu_set_running_timer(true);
217 : :
218 : : /* Now we can unlock and call it's expiry */
219 : 0 : unlock(&timer_lock);
220 : 0 : t->expiry(t, t->user_data, now);
221 : :
222 : : /* Re-lock and mark not running */
223 : 0 : lock(&timer_lock);
224 : 0 : this_cpu_set_running_timer(false);
225 : 0 : t->running = NULL;
226 : : }
227 : 65466 : timer_in_poll = false;
228 : : }
229 : :
230 : 65566 : static void __check_timers(uint64_t now)
231 : : {
232 : : struct timer *t;
233 : :
234 : : for (;;) {
235 : 65566 : t = list_top(&timer_list, struct timer, link);
236 : :
237 : : /* Top of list not expired ? that's it ... */
238 : 65566 : if (!t)
239 : 1 : break;
240 : 65565 : if (t->target > now) {
241 : 65465 : update_timer_expiry(t->target);
242 : 65465 : break;
243 : : }
244 : :
245 : : /* Top of list still running, we have to delay handling
246 : : * it. For now just skip until the next poll, when we have
247 : : * SLW interrupts, we'll probably want to trip another one
248 : : * ASAP
249 : : */
250 : 100 : if (t->running)
251 : 0 : break;
252 : :
253 : : /* Allright, first remove it and mark it running */
254 : 100 : __remove_timer(t);
255 : 100 : t->running = this_cpu();
256 : 100 : this_cpu_set_running_timer(true);
257 : :
258 : : /* Now we can unlock and call it's expiry */
259 : 100 : unlock(&timer_lock);
260 : 100 : t->expiry(t, t->user_data, now);
261 : :
262 : : /* Re-lock and mark not running */
263 : 100 : lock(&timer_lock);
264 : 100 : this_cpu_set_running_timer(false);
265 : 100 : t->running = NULL;
266 : :
267 : : /* Update time stamp */
268 : 100 : now = mftb();
269 : : }
270 : 65466 : }
271 : :
272 : 65466 : void check_timers(bool from_interrupt)
273 : : {
274 : 65466 : uint64_t now = mftb();
275 : :
276 : : /* This is the polling variant, the SLW interrupt path, when it
277 : : * exists, will use a slight variant of this that doesn't call
278 : : * the pollers
279 : : */
280 : :
281 : : /* Lockless "peek", a bit racy but shouldn't be a problem as
282 : : * we are only looking at whether the list is empty
283 : : */
284 : 130932 : if (list_empty_nocheck(&timer_poll_list) &&
285 : 65466 : list_empty_nocheck(&timer_list))
286 : 0 : return;
287 : :
288 : : /* Take lock and try again */
289 : 65466 : lock(&timer_lock);
290 : 65466 : if (!from_interrupt)
291 : 65466 : __check_poll_timers(now);
292 : 65466 : __check_timers(now);
293 : 65466 : unlock(&timer_lock);
294 : : }
295 : :
296 : : #ifndef __TEST__
297 : :
298 : : void late_init_timers(void)
299 : : {
300 : : int heartbeat = HEARTBEAT_DEFAULT_MS;
301 : :
302 : : /* Add a property requesting the OS to call opal_poll_event() at
303 : : * a specified interval in order for us to run our background
304 : : * low priority pollers.
305 : : *
306 : : * If a platform quirk exists, use that, else use the default.
307 : : *
308 : : * If we have an SBE timer facility, we run this 10 times slower,
309 : : * we could possibly completely get rid of it.
310 : : *
311 : : * We use a value in milliseconds, we don't want this to ever be
312 : : * faster than that.
313 : : */
314 : : if (platform.heartbeat_time) {
315 : : heartbeat = platform.heartbeat_time();
316 : : } else if (sbe_timer_present()) {
317 : : heartbeat = HEARTBEAT_DEFAULT_MS * 10;
318 : : }
319 : :
320 : : dt_add_property_cells(opal_node, "ibm,heartbeat-ms", heartbeat);
321 : : }
322 : : #endif
|