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