1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * SCMI Generic SystemPower Control driver.
4 *
5 * Copyright (C) 2020-2022 ARM Ltd.
6 */
7 /*
8 * In order to handle platform originated SCMI SystemPower requests (like
9 * shutdowns or cold/warm resets) we register an SCMI Notification notifier
10 * block to react when such SCMI SystemPower events are emitted by platform.
11 *
12 * Once such a notification is received we act accordingly to perform the
13 * required system transition depending on the kind of request.
14 *
15 * Graceful requests are routed to userspace through the same API methods
16 * (orderly_poweroff/reboot()) used by ACPI when handling ACPI Shutdown bus
17 * events.
18 *
19 * Direct forceful requests are not supported since are not meant to be sent
20 * by the SCMI platform to an OSPM like Linux.
21 *
22 * Additionally, graceful request notifications can carry an optional timeout
23 * field stating the maximum amount of time allowed by the platform for
24 * completion after which they are converted to forceful ones: the assumption
25 * here is that even graceful requests can be upper-bound by a maximum final
26 * timeout strictly enforced by the platform itself which can ultimately cut
27 * the power off at will anytime; in order to avoid such extreme scenario, we
28 * track progress of graceful requests through the means of a reboot notifier
29 * converting timed-out graceful requests to forceful ones, so at least we
30 * try to perform a clean sync and shutdown/restart before the power is cut.
31 *
32 * Given the peculiar nature of SCMI SystemPower protocol, that is being in
33 * charge of triggering system wide shutdown/reboot events, there should be
34 * only one SCMI platform actively emitting SystemPower events.
35 * For this reason the SCMI core takes care to enforce the creation of one
36 * single unique device associated to the SCMI System Power protocol; no matter
37 * how many SCMI platforms are defined on the system, only one can be designated
38 * to support System Power: as a consequence this driver will never be probed
39 * more than once.
40 *
41 * For similar reasons as soon as the first valid SystemPower is received by
42 * this driver and the shutdown/reboot is started, any further notification
43 * possibly emitted by the platform will be ignored.
44 */
45
46 #include <linux/math.h>
47 #include <linux/module.h>
48 #include <linux/mutex.h>
49 #include <linux/printk.h>
50 #include <linux/reboot.h>
51 #include <linux/scmi_protocol.h>
52 #include <linux/slab.h>
53 #include <linux/suspend.h>
54 #include <linux/time64.h>
55 #include <linux/timer.h>
56 #include <linux/types.h>
57 #include <linux/workqueue.h>
58
59 #ifndef MODULE
60 #include <linux/fs.h>
61 #endif
62
63 enum scmi_syspower_state {
64 SCMI_SYSPOWER_IDLE,
65 SCMI_SYSPOWER_IN_PROGRESS,
66 SCMI_SYSPOWER_REBOOTING
67 };
68
69 /**
70 * struct scmi_syspower_conf - Common configuration
71 *
72 * @dev: A reference device
73 * @state: Current SystemPower state
74 * @state_mtx: @state related mutex
75 * @required_transition: The requested transition as decribed in the received
76 * SCMI SystemPower notification
77 * @userspace_nb: The notifier_block registered against the SCMI SystemPower
78 * notification to start the needed userspace interactions.
79 * @reboot_nb: A notifier_block optionally used to track reboot progress
80 * @forceful_work: A worker used to trigger a forceful transition once a
81 * graceful has timed out.
82 * @suspend_work: A worker used to trigger system suspend
83 */
84 struct scmi_syspower_conf {
85 struct device *dev;
86 enum scmi_syspower_state state;
87 /* Protect access to state */
88 struct mutex state_mtx;
89 enum scmi_system_events required_transition;
90
91 struct notifier_block userspace_nb;
92 struct notifier_block reboot_nb;
93
94 struct delayed_work forceful_work;
95 struct work_struct suspend_work;
96 };
97
98 #define userspace_nb_to_sconf(x) \
99 container_of(x, struct scmi_syspower_conf, userspace_nb)
100
101 #define reboot_nb_to_sconf(x) \
102 container_of(x, struct scmi_syspower_conf, reboot_nb)
103
104 #define dwork_to_sconf(x) \
105 container_of(x, struct scmi_syspower_conf, forceful_work)
106
107 /**
108 * scmi_reboot_notifier - A reboot notifier to catch an ongoing successful
109 * system transition
110 * @nb: Reference to the related notifier block
111 * @reason: The reason for the ongoing reboot
112 * @__unused: The cmd being executed on a restart request (unused)
113 *
114 * When an ongoing system transition is detected, compatible with the one
115 * requested by SCMI, cancel the delayed work.
116 *
117 * Return: NOTIFY_OK in any case
118 */
scmi_reboot_notifier(struct notifier_block * nb,unsigned long reason,void * __unused)119 static int scmi_reboot_notifier(struct notifier_block *nb,
120 unsigned long reason, void *__unused)
121 {
122 struct scmi_syspower_conf *sc = reboot_nb_to_sconf(nb);
123
124 mutex_lock(&sc->state_mtx);
125 switch (reason) {
126 case SYS_HALT:
127 case SYS_POWER_OFF:
128 if (sc->required_transition == SCMI_SYSTEM_SHUTDOWN)
129 sc->state = SCMI_SYSPOWER_REBOOTING;
130 break;
131 case SYS_RESTART:
132 if (sc->required_transition == SCMI_SYSTEM_COLDRESET ||
133 sc->required_transition == SCMI_SYSTEM_WARMRESET)
134 sc->state = SCMI_SYSPOWER_REBOOTING;
135 break;
136 default:
137 break;
138 }
139
140 if (sc->state == SCMI_SYSPOWER_REBOOTING) {
141 dev_dbg(sc->dev, "Reboot in progress...cancel delayed work.\n");
142 cancel_delayed_work_sync(&sc->forceful_work);
143 }
144 mutex_unlock(&sc->state_mtx);
145
146 return NOTIFY_OK;
147 }
148
149 /**
150 * scmi_request_forceful_transition - Request forceful SystemPower transition
151 * @sc: A reference to the configuration data
152 *
153 * Initiates the required SystemPower transition without involving userspace:
154 * just trigger the action at the kernel level after issuing an emergency
155 * sync. (if possible at all)
156 */
157 static inline void
scmi_request_forceful_transition(struct scmi_syspower_conf * sc)158 scmi_request_forceful_transition(struct scmi_syspower_conf *sc)
159 {
160 dev_dbg(sc->dev, "Serving forceful request:%d\n",
161 sc->required_transition);
162
163 #ifndef MODULE
164 emergency_sync();
165 #endif
166 switch (sc->required_transition) {
167 case SCMI_SYSTEM_SHUTDOWN:
168 kernel_power_off();
169 break;
170 case SCMI_SYSTEM_COLDRESET:
171 case SCMI_SYSTEM_WARMRESET:
172 kernel_restart(NULL);
173 break;
174 default:
175 break;
176 }
177 }
178
scmi_forceful_work_func(struct work_struct * work)179 static void scmi_forceful_work_func(struct work_struct *work)
180 {
181 struct scmi_syspower_conf *sc;
182 struct delayed_work *dwork;
183
184 if (system_state > SYSTEM_RUNNING)
185 return;
186
187 dwork = to_delayed_work(work);
188 sc = dwork_to_sconf(dwork);
189
190 dev_dbg(sc->dev, "Graceful request timed out...forcing !\n");
191 mutex_lock(&sc->state_mtx);
192 /* avoid deadlock by unregistering reboot notifier first */
193 unregister_reboot_notifier(&sc->reboot_nb);
194 if (sc->state == SCMI_SYSPOWER_IN_PROGRESS)
195 scmi_request_forceful_transition(sc);
196 mutex_unlock(&sc->state_mtx);
197 }
198
199 /**
200 * scmi_request_graceful_transition - Request graceful SystemPower transition
201 * @sc: A reference to the configuration data
202 * @timeout_ms: The desired timeout to wait for the shutdown to complete before
203 * system is forcibly shutdown.
204 *
205 * Initiates the required SystemPower transition, requesting userspace
206 * co-operation: it uses the same orderly_ methods used by ACPI Shutdown event
207 * processing.
208 *
209 * Takes care also to register a reboot notifier and to schedule a delayed work
210 * in order to detect if userspace actions are taking too long and in such a
211 * case to trigger a forceful transition.
212 */
scmi_request_graceful_transition(struct scmi_syspower_conf * sc,unsigned int timeout_ms)213 static void scmi_request_graceful_transition(struct scmi_syspower_conf *sc,
214 unsigned int timeout_ms)
215 {
216 unsigned int adj_timeout_ms = 0;
217
218 if (timeout_ms) {
219 int ret;
220
221 sc->reboot_nb.notifier_call = &scmi_reboot_notifier;
222 ret = register_reboot_notifier(&sc->reboot_nb);
223 if (!ret) {
224 /* Wait only up to 75% of the advertised timeout */
225 adj_timeout_ms = mult_frac(timeout_ms, 3, 4);
226 INIT_DELAYED_WORK(&sc->forceful_work,
227 scmi_forceful_work_func);
228 schedule_delayed_work(&sc->forceful_work,
229 msecs_to_jiffies(adj_timeout_ms));
230 } else {
231 /* Carry on best effort even without a reboot notifier */
232 dev_warn(sc->dev,
233 "Cannot register reboot notifier !\n");
234 }
235 }
236
237 dev_dbg(sc->dev,
238 "Serving graceful req:%d (timeout_ms:%u adj_timeout_ms:%u)\n",
239 sc->required_transition, timeout_ms, adj_timeout_ms);
240
241 switch (sc->required_transition) {
242 case SCMI_SYSTEM_SHUTDOWN:
243 /*
244 * When triggered early at boot-time the 'orderly' call will
245 * partially fail due to the lack of userspace itself, but
246 * the force=true argument will start anyway a successful
247 * forced shutdown.
248 */
249 orderly_poweroff(true);
250 break;
251 case SCMI_SYSTEM_COLDRESET:
252 case SCMI_SYSTEM_WARMRESET:
253 orderly_reboot();
254 break;
255 case SCMI_SYSTEM_SUSPEND:
256 schedule_work(&sc->suspend_work);
257 break;
258 default:
259 break;
260 }
261 }
262
263 /**
264 * scmi_userspace_notifier - Notifier callback to act on SystemPower
265 * Notifications
266 * @nb: Reference to the related notifier block
267 * @event: The SystemPower notification event id
268 * @data: The SystemPower event report
269 *
270 * This callback is in charge of decoding the received SystemPower report
271 * and act accordingly triggering a graceful or forceful system transition.
272 *
273 * Note that once a valid SCMI SystemPower event starts being served, any
274 * other following SystemPower notification received from the same SCMI
275 * instance (handle) will be ignored.
276 *
277 * Return: NOTIFY_OK once a valid SystemPower event has been successfully
278 * processed.
279 */
scmi_userspace_notifier(struct notifier_block * nb,unsigned long event,void * data)280 static int scmi_userspace_notifier(struct notifier_block *nb,
281 unsigned long event, void *data)
282 {
283 struct scmi_system_power_state_notifier_report *er = data;
284 struct scmi_syspower_conf *sc = userspace_nb_to_sconf(nb);
285
286 if (er->system_state >= SCMI_SYSTEM_MAX ||
287 er->system_state == SCMI_SYSTEM_POWERUP) {
288 dev_err(sc->dev, "Ignoring unsupported system_state: 0x%X\n",
289 er->system_state);
290 return NOTIFY_DONE;
291 }
292
293 if (!SCMI_SYSPOWER_IS_REQUEST_GRACEFUL(er->flags)) {
294 dev_err(sc->dev, "Ignoring forceful notification.\n");
295 return NOTIFY_DONE;
296 }
297
298 /*
299 * Bail out if system is already shutting down or an SCMI SystemPower
300 * requested is already being served.
301 */
302 if (system_state > SYSTEM_RUNNING)
303 return NOTIFY_DONE;
304 mutex_lock(&sc->state_mtx);
305 if (sc->state != SCMI_SYSPOWER_IDLE) {
306 dev_dbg(sc->dev,
307 "Transition already in progress...ignore.\n");
308 mutex_unlock(&sc->state_mtx);
309 return NOTIFY_DONE;
310 }
311 sc->state = SCMI_SYSPOWER_IN_PROGRESS;
312 mutex_unlock(&sc->state_mtx);
313
314 sc->required_transition = er->system_state;
315
316 /* Leaving a trace in logs of who triggered the shutdown/reboot. */
317 dev_info(sc->dev, "Serving shutdown/reboot request: %d\n",
318 sc->required_transition);
319
320 scmi_request_graceful_transition(sc, er->timeout);
321
322 return NOTIFY_OK;
323 }
324
scmi_suspend_work_func(struct work_struct * work)325 static void scmi_suspend_work_func(struct work_struct *work)
326 {
327 struct scmi_syspower_conf *sc =
328 container_of(work, struct scmi_syspower_conf, suspend_work);
329
330 pm_suspend(PM_SUSPEND_MEM);
331
332 sc->state = SCMI_SYSPOWER_IDLE;
333 }
334
scmi_syspower_probe(struct scmi_device * sdev)335 static int scmi_syspower_probe(struct scmi_device *sdev)
336 {
337 int ret;
338 struct scmi_syspower_conf *sc;
339 struct scmi_handle *handle = sdev->handle;
340
341 if (!handle)
342 return -ENODEV;
343
344 ret = handle->devm_protocol_acquire(sdev, SCMI_PROTOCOL_SYSTEM);
345 if (ret)
346 return ret;
347
348 sc = devm_kzalloc(&sdev->dev, sizeof(*sc), GFP_KERNEL);
349 if (!sc)
350 return -ENOMEM;
351
352 sc->state = SCMI_SYSPOWER_IDLE;
353 mutex_init(&sc->state_mtx);
354 sc->required_transition = SCMI_SYSTEM_MAX;
355 sc->userspace_nb.notifier_call = &scmi_userspace_notifier;
356 sc->dev = &sdev->dev;
357
358 INIT_WORK(&sc->suspend_work, scmi_suspend_work_func);
359
360 return handle->notify_ops->devm_event_notifier_register(sdev,
361 SCMI_PROTOCOL_SYSTEM,
362 SCMI_EVENT_SYSTEM_POWER_STATE_NOTIFIER,
363 NULL, &sc->userspace_nb);
364 }
365
366 static const struct scmi_device_id scmi_id_table[] = {
367 { SCMI_PROTOCOL_SYSTEM, "syspower" },
368 { },
369 };
370 MODULE_DEVICE_TABLE(scmi, scmi_id_table);
371
372 static struct scmi_driver scmi_system_power_driver = {
373 .name = "scmi-system-power",
374 .probe = scmi_syspower_probe,
375 .id_table = scmi_id_table,
376 };
377 module_scmi_driver(scmi_system_power_driver);
378
379 MODULE_AUTHOR("Cristian Marussi <cristian.marussi@arm.com>");
380 MODULE_DESCRIPTION("ARM SCMI SystemPower Control driver");
381 MODULE_LICENSE("GPL");
382