PM: console: Fix memory allocation error handling in pm_vt_switch_required()

The pm_vt_switch_required() function fails silently when memory
allocation fails, offering no indication to callers that the operation
was unsuccessful. This behavior prevents drivers from handling allocation
errors correctly or implementing retry mechanisms. By ensuring that
failures are reported back to the caller, drivers can make informed
decisions, improve robustness, and avoid unexpected behavior during
critical power management operations.

Change the function signature to return an integer error code and modify
the implementation to return -ENOMEM when kmalloc() fails. Update both
the function declaration and the inline stub in include/linux/pm.h to
maintain consistency across CONFIG_VT_CONSOLE_SLEEP configurations.

The function now returns:
 - 0 on success (including when updating existing entries)
 - -ENOMEM when memory allocation fails

This change improves error reporting without breaking existing callers,
as the current callers in drivers/video/fbdev/core/fbmem.c already
ignore the return value, making this a backward-compatible improvement.

Reviewed-by: Lyude Paul <lyude@redhat.com>
Signed-off-by: Malaya Kumar Rout <mrout@redhat.com>
Reviewed-by: Dhruva Gole <d-gole@ti.com>
Reviewed-by: Lyude Paul <lyude@redhat.com>
Link: https://patch.msgid.link/20251013193028.89570-1-mrout@redhat.com
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
Malaya Kumar Rout 2025-10-14 01:00:27 +05:30 committed by Rafael J. Wysocki
parent 67434ce57c
commit b57100a3d9
2 changed files with 9 additions and 4 deletions

View File

@ -25,11 +25,12 @@ extern void (*pm_power_off)(void);
struct device; /* we have a circular dep with device.h */ struct device; /* we have a circular dep with device.h */
#ifdef CONFIG_VT_CONSOLE_SLEEP #ifdef CONFIG_VT_CONSOLE_SLEEP
extern void pm_vt_switch_required(struct device *dev, bool required); extern int pm_vt_switch_required(struct device *dev, bool required);
extern void pm_vt_switch_unregister(struct device *dev); extern void pm_vt_switch_unregister(struct device *dev);
#else #else
static inline void pm_vt_switch_required(struct device *dev, bool required) static inline int pm_vt_switch_required(struct device *dev, bool required)
{ {
return 0;
} }
static inline void pm_vt_switch_unregister(struct device *dev) static inline void pm_vt_switch_unregister(struct device *dev)
{ {

View File

@ -44,9 +44,10 @@ static LIST_HEAD(pm_vt_switch_list);
* no_console_suspend argument has been passed on the command line, VT * no_console_suspend argument has been passed on the command line, VT
* switches will occur. * switches will occur.
*/ */
void pm_vt_switch_required(struct device *dev, bool required) int pm_vt_switch_required(struct device *dev, bool required)
{ {
struct pm_vt_switch *entry, *tmp; struct pm_vt_switch *entry, *tmp;
int ret = 0;
mutex_lock(&vt_switch_mutex); mutex_lock(&vt_switch_mutex);
list_for_each_entry(tmp, &pm_vt_switch_list, head) { list_for_each_entry(tmp, &pm_vt_switch_list, head) {
@ -58,8 +59,10 @@ void pm_vt_switch_required(struct device *dev, bool required)
} }
entry = kmalloc(sizeof(*entry), GFP_KERNEL); entry = kmalloc(sizeof(*entry), GFP_KERNEL);
if (!entry) if (!entry) {
ret = -ENOMEM;
goto out; goto out;
}
entry->required = required; entry->required = required;
entry->dev = dev; entry->dev = dev;
@ -67,6 +70,7 @@ void pm_vt_switch_required(struct device *dev, bool required)
list_add(&entry->head, &pm_vt_switch_list); list_add(&entry->head, &pm_vt_switch_list);
out: out:
mutex_unlock(&vt_switch_mutex); mutex_unlock(&vt_switch_mutex);
return ret;
} }
EXPORT_SYMBOL(pm_vt_switch_required); EXPORT_SYMBOL(pm_vt_switch_required);