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/time64.h> 54 #include <linux/timer.h> 55 #include <linux/types.h> 56 #include <linux/workqueue.h> 57 58 #ifndef MODULE 59 #include <linux/fs.h> 60 #endif 61 62 enum scmi_syspower_state { 63 SCMI_SYSPOWER_IDLE, 64 SCMI_SYSPOWER_IN_PROGRESS, 65 SCMI_SYSPOWER_REBOOTING 66 }; 67 68 /** 69 * struct scmi_syspower_conf - Common configuration 70 * 71 * @dev: A reference device 72 * @state: Current SystemPower state 73 * @state_mtx: @state related mutex 74 * @required_transition: The requested transition as decribed in the received 75 * SCMI SystemPower notification 76 * @userspace_nb: The notifier_block registered against the SCMI SystemPower 77 * notification to start the needed userspace interactions. 78 * @reboot_nb: A notifier_block optionally used to track reboot progress 79 * @forceful_work: A worker used to trigger a forceful transition once a 80 * graceful has timed out. 81 */ 82 struct scmi_syspower_conf { 83 struct device *dev; 84 enum scmi_syspower_state state; 85 /* Protect access to state */ 86 struct mutex state_mtx; 87 enum scmi_system_events required_transition; 88 89 struct notifier_block userspace_nb; 90 struct notifier_block reboot_nb; 91 92 struct delayed_work forceful_work; 93 }; 94 95 #define userspace_nb_to_sconf(x) \ 96 container_of(x, struct scmi_syspower_conf, userspace_nb) 97 98 #define reboot_nb_to_sconf(x) \ 99 container_of(x, struct scmi_syspower_conf, reboot_nb) 100 101 #define dwork_to_sconf(x) \ 102 container_of(x, struct scmi_syspower_conf, forceful_work) 103 104 /** 105 * scmi_reboot_notifier - A reboot notifier to catch an ongoing successful 106 * system transition 107 * @nb: Reference to the related notifier block 108 * @reason: The reason for the ongoing reboot 109 * @__unused: The cmd being executed on a restart request (unused) 110 * 111 * When an ongoing system transition is detected, compatible with the one 112 * requested by SCMI, cancel the delayed work. 113 * 114 * Return: NOTIFY_OK in any case 115 */ 116 static int scmi_reboot_notifier(struct notifier_block *nb, 117 unsigned long reason, void *__unused) 118 { 119 struct scmi_syspower_conf *sc = reboot_nb_to_sconf(nb); 120 121 mutex_lock(&sc->state_mtx); 122 switch (reason) { 123 case SYS_HALT: 124 case SYS_POWER_OFF: 125 if (sc->required_transition == SCMI_SYSTEM_SHUTDOWN) 126 sc->state = SCMI_SYSPOWER_REBOOTING; 127 break; 128 case SYS_RESTART: 129 if (sc->required_transition == SCMI_SYSTEM_COLDRESET || 130 sc->required_transition == SCMI_SYSTEM_WARMRESET) 131 sc->state = SCMI_SYSPOWER_REBOOTING; 132 break; 133 default: 134 break; 135 } 136 137 if (sc->state == SCMI_SYSPOWER_REBOOTING) { 138 dev_dbg(sc->dev, "Reboot in progress...cancel delayed work.\n"); 139 cancel_delayed_work_sync(&sc->forceful_work); 140 } 141 mutex_unlock(&sc->state_mtx); 142 143 return NOTIFY_OK; 144 } 145 146 /** 147 * scmi_request_forceful_transition - Request forceful SystemPower transition 148 * @sc: A reference to the configuration data 149 * 150 * Initiates the required SystemPower transition without involving userspace: 151 * just trigger the action at the kernel level after issuing an emergency 152 * sync. (if possible at all) 153 */ 154 static inline void 155 scmi_request_forceful_transition(struct scmi_syspower_conf *sc) 156 { 157 dev_dbg(sc->dev, "Serving forceful request:%d\n", 158 sc->required_transition); 159 160 #ifndef MODULE 161 emergency_sync(); 162 #endif 163 switch (sc->required_transition) { 164 case SCMI_SYSTEM_SHUTDOWN: 165 kernel_power_off(); 166 break; 167 case SCMI_SYSTEM_COLDRESET: 168 case SCMI_SYSTEM_WARMRESET: 169 kernel_restart(NULL); 170 break; 171 default: 172 break; 173 } 174 } 175 176 static void scmi_forceful_work_func(struct work_struct *work) 177 { 178 struct scmi_syspower_conf *sc; 179 struct delayed_work *dwork; 180 181 if (system_state > SYSTEM_RUNNING) 182 return; 183 184 dwork = to_delayed_work(work); 185 sc = dwork_to_sconf(dwork); 186 187 dev_dbg(sc->dev, "Graceful request timed out...forcing !\n"); 188 mutex_lock(&sc->state_mtx); 189 /* avoid deadlock by unregistering reboot notifier first */ 190 unregister_reboot_notifier(&sc->reboot_nb); 191 if (sc->state == SCMI_SYSPOWER_IN_PROGRESS) 192 scmi_request_forceful_transition(sc); 193 mutex_unlock(&sc->state_mtx); 194 } 195 196 /** 197 * scmi_request_graceful_transition - Request graceful SystemPower transition 198 * @sc: A reference to the configuration data 199 * @timeout_ms: The desired timeout to wait for the shutdown to complete before 200 * system is forcibly shutdown. 201 * 202 * Initiates the required SystemPower transition, requesting userspace 203 * co-operation: it uses the same orderly_ methods used by ACPI Shutdown event 204 * processing. 205 * 206 * Takes care also to register a reboot notifier and to schedule a delayed work 207 * in order to detect if userspace actions are taking too long and in such a 208 * case to trigger a forceful transition. 209 */ 210 static void scmi_request_graceful_transition(struct scmi_syspower_conf *sc, 211 unsigned int timeout_ms) 212 { 213 unsigned int adj_timeout_ms = 0; 214 215 if (timeout_ms) { 216 int ret; 217 218 sc->reboot_nb.notifier_call = &scmi_reboot_notifier; 219 ret = register_reboot_notifier(&sc->reboot_nb); 220 if (!ret) { 221 /* Wait only up to 75% of the advertised timeout */ 222 adj_timeout_ms = mult_frac(timeout_ms, 3, 4); 223 INIT_DELAYED_WORK(&sc->forceful_work, 224 scmi_forceful_work_func); 225 schedule_delayed_work(&sc->forceful_work, 226 msecs_to_jiffies(adj_timeout_ms)); 227 } else { 228 /* Carry on best effort even without a reboot notifier */ 229 dev_warn(sc->dev, 230 "Cannot register reboot notifier !\n"); 231 } 232 } 233 234 dev_dbg(sc->dev, 235 "Serving graceful req:%d (timeout_ms:%u adj_timeout_ms:%u)\n", 236 sc->required_transition, timeout_ms, adj_timeout_ms); 237 238 switch (sc->required_transition) { 239 case SCMI_SYSTEM_SHUTDOWN: 240 /* 241 * When triggered early at boot-time the 'orderly' call will 242 * partially fail due to the lack of userspace itself, but 243 * the force=true argument will start anyway a successful 244 * forced shutdown. 245 */ 246 orderly_poweroff(true); 247 break; 248 case SCMI_SYSTEM_COLDRESET: 249 case SCMI_SYSTEM_WARMRESET: 250 orderly_reboot(); 251 break; 252 default: 253 break; 254 } 255 } 256 257 /** 258 * scmi_userspace_notifier - Notifier callback to act on SystemPower 259 * Notifications 260 * @nb: Reference to the related notifier block 261 * @event: The SystemPower notification event id 262 * @data: The SystemPower event report 263 * 264 * This callback is in charge of decoding the received SystemPower report 265 * and act accordingly triggering a graceful or forceful system transition. 266 * 267 * Note that once a valid SCMI SystemPower event starts being served, any 268 * other following SystemPower notification received from the same SCMI 269 * instance (handle) will be ignored. 270 * 271 * Return: NOTIFY_OK once a valid SystemPower event has been successfully 272 * processed. 273 */ 274 static int scmi_userspace_notifier(struct notifier_block *nb, 275 unsigned long event, void *data) 276 { 277 struct scmi_system_power_state_notifier_report *er = data; 278 struct scmi_syspower_conf *sc = userspace_nb_to_sconf(nb); 279 280 if (er->system_state >= SCMI_SYSTEM_POWERUP) { 281 dev_err(sc->dev, "Ignoring unsupported system_state: 0x%X\n", 282 er->system_state); 283 return NOTIFY_DONE; 284 } 285 286 if (!SCMI_SYSPOWER_IS_REQUEST_GRACEFUL(er->flags)) { 287 dev_err(sc->dev, "Ignoring forceful notification.\n"); 288 return NOTIFY_DONE; 289 } 290 291 /* 292 * Bail out if system is already shutting down or an SCMI SystemPower 293 * requested is already being served. 294 */ 295 if (system_state > SYSTEM_RUNNING) 296 return NOTIFY_DONE; 297 mutex_lock(&sc->state_mtx); 298 if (sc->state != SCMI_SYSPOWER_IDLE) { 299 dev_dbg(sc->dev, 300 "Transition already in progress...ignore.\n"); 301 mutex_unlock(&sc->state_mtx); 302 return NOTIFY_DONE; 303 } 304 sc->state = SCMI_SYSPOWER_IN_PROGRESS; 305 mutex_unlock(&sc->state_mtx); 306 307 sc->required_transition = er->system_state; 308 309 /* Leaving a trace in logs of who triggered the shutdown/reboot. */ 310 dev_info(sc->dev, "Serving shutdown/reboot request: %d\n", 311 sc->required_transition); 312 313 scmi_request_graceful_transition(sc, er->timeout); 314 315 return NOTIFY_OK; 316 } 317 318 static int scmi_syspower_probe(struct scmi_device *sdev) 319 { 320 int ret; 321 struct scmi_syspower_conf *sc; 322 struct scmi_handle *handle = sdev->handle; 323 324 if (!handle) 325 return -ENODEV; 326 327 ret = handle->devm_protocol_acquire(sdev, SCMI_PROTOCOL_SYSTEM); 328 if (ret) 329 return ret; 330 331 sc = devm_kzalloc(&sdev->dev, sizeof(*sc), GFP_KERNEL); 332 if (!sc) 333 return -ENOMEM; 334 335 sc->state = SCMI_SYSPOWER_IDLE; 336 mutex_init(&sc->state_mtx); 337 sc->required_transition = SCMI_SYSTEM_MAX; 338 sc->userspace_nb.notifier_call = &scmi_userspace_notifier; 339 sc->dev = &sdev->dev; 340 341 return handle->notify_ops->devm_event_notifier_register(sdev, 342 SCMI_PROTOCOL_SYSTEM, 343 SCMI_EVENT_SYSTEM_POWER_STATE_NOTIFIER, 344 NULL, &sc->userspace_nb); 345 } 346 347 static const struct scmi_device_id scmi_id_table[] = { 348 { SCMI_PROTOCOL_SYSTEM, "syspower" }, 349 { }, 350 }; 351 MODULE_DEVICE_TABLE(scmi, scmi_id_table); 352 353 static struct scmi_driver scmi_system_power_driver = { 354 .name = "scmi-system-power", 355 .probe = scmi_syspower_probe, 356 .id_table = scmi_id_table, 357 }; 358 module_scmi_driver(scmi_system_power_driver); 359 360 MODULE_AUTHOR("Cristian Marussi <cristian.marussi@arm.com>"); 361 MODULE_DESCRIPTION("ARM SCMI SystemPower Control driver"); 362 MODULE_LICENSE("GPL"); 363