Skip to content

Commit 587b9bf

Browse files
digetxrafaeljw
authored andcommitted
kernel/reboot: Use static handler for register_platform_power_off()
The register_platform_power_off() fails on m68k platform due to the memory allocation error that happens at a very early boot time when memory allocator isn't available yet. Fix it by using a static sys-off handler for the platform-level power-off handlers. Fixes: f0f7e52 ("m68k: Switch to new sys-off handler API") Reported-by: Geert Uytterhoeven <[email protected]> Signed-off-by: Dmitry Osipenko <[email protected]> Reviewed-by: Geert Uytterhoeven <[email protected]> Tested-by: Geert Uytterhoeven <[email protected]> Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent 1ff7bc3 commit 587b9bf

File tree

1 file changed

+37
-6
lines changed

1 file changed

+37
-6
lines changed

kernel/reboot.c

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,37 @@ static int sys_off_notify(struct notifier_block *nb,
315315
return handler->sys_off_cb(&data);
316316
}
317317

318+
static struct sys_off_handler platform_sys_off_handler;
319+
320+
static struct sys_off_handler *alloc_sys_off_handler(int priority)
321+
{
322+
struct sys_off_handler *handler;
323+
324+
/*
325+
* Platforms like m68k can't allocate sys_off handler dynamically
326+
* at the early boot time because memory allocator isn't available yet.
327+
*/
328+
if (priority == SYS_OFF_PRIO_PLATFORM) {
329+
handler = &platform_sys_off_handler;
330+
if (handler->cb_data)
331+
return ERR_PTR(-EBUSY);
332+
} else {
333+
handler = kzalloc(sizeof(*handler), GFP_KERNEL);
334+
if (!handler)
335+
return ERR_PTR(-ENOMEM);
336+
}
337+
338+
return handler;
339+
}
340+
341+
static void free_sys_off_handler(struct sys_off_handler *handler)
342+
{
343+
if (handler == &platform_sys_off_handler)
344+
memset(handler, 0, sizeof(*handler));
345+
else
346+
kfree(handler);
347+
}
348+
318349
/**
319350
* register_sys_off_handler - Register sys-off handler
320351
* @mode: Sys-off mode
@@ -345,9 +376,9 @@ register_sys_off_handler(enum sys_off_mode mode,
345376
struct sys_off_handler *handler;
346377
int err;
347378

348-
handler = kzalloc(sizeof(*handler), GFP_KERNEL);
349-
if (!handler)
350-
return ERR_PTR(-ENOMEM);
379+
handler = alloc_sys_off_handler(priority);
380+
if (IS_ERR(handler))
381+
return handler;
351382

352383
switch (mode) {
353384
case SYS_OFF_MODE_POWER_OFF_PREPARE:
@@ -364,7 +395,7 @@ register_sys_off_handler(enum sys_off_mode mode,
364395
break;
365396

366397
default:
367-
kfree(handler);
398+
free_sys_off_handler(handler);
368399
return ERR_PTR(-EINVAL);
369400
}
370401

@@ -391,7 +422,7 @@ register_sys_off_handler(enum sys_off_mode mode,
391422
}
392423

393424
if (err) {
394-
kfree(handler);
425+
free_sys_off_handler(handler);
395426
return ERR_PTR(err);
396427
}
397428

@@ -422,7 +453,7 @@ void unregister_sys_off_handler(struct sys_off_handler *handler)
422453
/* sanity check, shall never happen */
423454
WARN_ON(err);
424455

425-
kfree(handler);
456+
free_sys_off_handler(handler);
426457
}
427458
EXPORT_SYMBOL_GPL(unregister_sys_off_handler);
428459

0 commit comments

Comments
 (0)