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 */ 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 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 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 */ 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 */ 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 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 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