request_firmware API

You would typically load firmware and then load it into your device somehow. The typical firmware work flow is reflected below:

if(request_firmware(&fw_entry, $FIRMWARE, device) == 0)
       copy_fw_to_device(fw_entry->data, fw_entry->size);
release_firmware(fw_entry);

Synchronous firmware requests

Synchronous firmware requests will wait until the firmware is found or until an error is returned.

request_firmware

int request_firmware(const struct firmware ** firmware_p, const char * name, struct device * device)

send firmware request and wait for it

Parameters

const struct firmware ** firmware_p
pointer to firmware image
const char * name
name of firmware file
struct device * device
device for which firmware is being loaded

Description

firmware_p will be used to return a firmware image by the name of name for device device.

Should be called from user context where sleeping is allowed.

name will be used as $FIRMWARE in the uevent environment and should be distinctive enough not to be confused with any other firmware image for this or any other device.

Caller must hold the reference count of device.

The function can be called safely inside device’s suspend and resume callback.

request_firmware_direct

int request_firmware_direct(const struct firmware ** firmware_p, const char * name, struct device * device)

load firmware directly without usermode helper

Parameters

const struct firmware ** firmware_p
pointer to firmware image
const char * name
name of firmware file
struct device * device
device for which firmware is being loaded

Description

This function works pretty much like request_firmware(), but this doesn’t fall back to usermode helper even if the firmware couldn’t be loaded directly from fs. Hence it’s useful for loading optional firmwares, which aren’t always present, without extra long timeouts of udev.

request_firmware_into_buf

int request_firmware_into_buf(const struct firmware ** firmware_p, const char * name, struct device * device, void * buf, size_t size)

load firmware into a previously allocated buffer

Parameters

const struct firmware ** firmware_p
pointer to firmware image
const char * name
name of firmware file
struct device * device
device for which firmware is being loaded and DMA region allocated
void * buf
address of buffer to load firmware into
size_t size
size of buffer

Description

This function works pretty much like request_firmware(), but it doesn’t allocate a buffer to hold the firmware data. Instead, the firmware is loaded directly into the buffer pointed to by buf and the firmware_p data member is pointed at buf.

This function doesn’t cache firmware either.

Asynchronous firmware requests

Asynchronous firmware requests allow driver code to not have to wait until the firmware or an error is returned. Function callbacks are provided so that when the firmware or an error is found the driver is informed through the callback. request_firmware_nowait() cannot be called in atomic contexts.

request_firmware_nowait

int request_firmware_nowait(struct module * module, bool uevent, const char * name, struct device * device, gfp_t gfp, void * context, void (*cont) (const struct firmware *fw, void *context)

asynchronous version of request_firmware

Parameters

struct module * module
module requesting the firmware
bool uevent
sends uevent to copy the firmware image if this flag is non-zero else the firmware copy must be done manually.
const char * name
name of firmware file
struct device * device
device for which firmware is being loaded
gfp_t gfp
allocation flags
void * context
will be passed over to cont, and fw may be NULL if firmware request fails.
void (*)(const struct firmware *fw, void *context) cont
function will be called asynchronously when the firmware request is over.

Description

Caller must hold the reference count of device.

Asynchronous variant of request_firmware() for user contexts:
  • sleep for as small periods as possible since it may increase kernel boot time of built-in device drivers requesting firmware in their ->:c:func:probe() methods, if gfp is GFP_KERNEL.
  • can’t sleep at all if gfp is GFP_ATOMIC.

Considerations for suspend and resume

During suspend and resume only the built-in firmware and the firmware cache elements of the firmware API can be used. This is managed by fw_pm_notify().

fw_pm_notify

int fw_pm_notify(struct notifier_block * notify_block, unsigned long mode, void * unused)

notifier for suspend/resume

Parameters

struct notifier_block * notify_block
unused
unsigned long mode
mode we are switching to
void * unused
unused

Description

Used to modify the firmware_class state as we move in between states. The firmware_class implements a firmware cache to enable device driver to fetch firmware upon resume before the root filesystem is ready. We disable API calls which do not use the built-in firmware or the firmware cache when we know these calls will not work.

The inner logic behind all this is a bit complex so it is worth summarizing the kernel’s own suspend/resume process with context and focus on how this can impact the firmware API.

First a review on how we go to suspend:

:c:func:`pm_suspend()` --> :c:func:`enter_state()` -->
:c:func:`sys_sync()`
:c:func:`suspend_prepare()` -->
        __pm_notifier_call_chain(PM_SUSPEND_PREPARE, ...);
        :c:func:`suspend_freeze_processes()` -->
                :c:func:`freeze_processes()` -->
                        __usermodehelper_set_disable_depth(UMH_DISABLED);
                        freeze all tasks ...
                :c:func:`freeze_kernel_threads()`
:c:func:`suspend_devices_and_enter()` -->
        :c:func:`dpm_suspend_start()` -->
                        :c:func:`dpm_prepare()`
                        :c:func:`dpm_suspend()`
        :c:func:`suspend_enter()`  -->
                :c:func:`platform_suspend_prepare()`
                :c:func:`dpm_suspend_late()`
                :c:func:`freeze_enter()`
                :c:func:`syscore_suspend()`

When we resume we bail out of a loop from suspend_devices_and_enter() and unwind back out to the caller enter_state() where we were before as follows:

:c:func:`enter_state()` -->
:c:func:`suspend_devices_and_enter()` --> (bail from loop)
        :c:func:`dpm_resume_end()` -->
                :c:func:`dpm_resume()`
                :c:func:`dpm_complete()`
:c:func:`suspend_finish()` -->
        :c:func:`suspend_thaw_processes()` -->
                :c:func:`thaw_processes()` -->
                        __usermodehelper_set_disable_depth(UMH_FREEZING);
                        :c:func:`thaw_workqueues()`;
                        thaw all processes ...
                        :c:func:`usermodehelper_enable()`;
        pm_notifier_call_chain(PM_POST_SUSPEND);

fw_pm_notify() works through pm_notifier_call_chain().

request firmware API expected driver use

Once an API call returns you process the firmware and then release the firmware. For example if you used request_firmware() and it returns, the driver has the firmware image accessible in fw_entry->{data,size}. If something went wrong request_firmware() returns non-zero and fw_entry is set to NULL. Once your driver is done with processing the firmware it can call call release_firmware(fw_entry) to release the firmware image and any related resource.