diff --git a/Documentation/driver-api/firmware/request_firmware.rst b/Documentation/driver-api/firmware/request_firmware.rst index cc0aea880824..cf4516dfbf96 100644 --- a/Documentation/driver-api/firmware/request_firmware.rst +++ b/Documentation/driver-api/firmware/request_firmware.rst @@ -44,6 +44,20 @@ request_firmware_nowait .. kernel-doc:: drivers/base/firmware_class.c :functions: request_firmware_nowait +Special optimizations on reboot +=============================== + +Some devices have an optimization in place to enable the firmware to be +retained during system reboot. When such optimizations are used the driver +author must ensure the firmware is still available on resume from suspend, +this can be done with firmware_request_cache() insted of requesting for the +firmare to be loaded. + +firmware_request_cache() +----------------------- +.. kernel-doc:: drivers/base/firmware_class.c + :functions: firmware_request_cache + request firmware API expected driver use ======================================== diff --git a/drivers/base/firmware_loader/main.c b/drivers/base/firmware_loader/main.c index 2913bb0e5e7b..eb34089e4299 100644 --- a/drivers/base/firmware_loader/main.c +++ b/drivers/base/firmware_loader/main.c @@ -656,6 +656,30 @@ int request_firmware_direct(const struct firmware **firmware_p, } EXPORT_SYMBOL_GPL(request_firmware_direct); +/** + * firmware_request_cache: - cache firmware for suspend so resume can use it + * @name: name of firmware file + * @device: device for which firmware should be cached for + * + * There are some devices with an optimization that enables the device to not + * require loading firmware on system reboot. This optimization may still + * require the firmware present on resume from suspend. This routine can be + * used to ensure the firmware is present on resume from suspend in these + * situations. This helper is not compatible with drivers which use + * request_firmware_into_buf() or request_firmware_nowait() with no uevent set. + **/ +int firmware_request_cache(struct device *device, const char *name) +{ + int ret; + + mutex_lock(&fw_lock); + ret = fw_add_devm_name(device, name); + mutex_unlock(&fw_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(firmware_request_cache); + /** * request_firmware_into_buf - load firmware into a previously allocated buffer * @firmware_p: pointer to firmware image diff --git a/include/linux/firmware.h b/include/linux/firmware.h index d4508080348d..41050417cafb 100644 --- a/include/linux/firmware.h +++ b/include/linux/firmware.h @@ -85,4 +85,7 @@ static inline int request_firmware_into_buf(const struct firmware **firmware_p, } #endif + +int firmware_request_cache(struct device *device, const char *name); + #endif