固件缓存¶
当 Linux 从挂起状态恢复时,某些设备驱动程序需要查找固件以重新初始化设备。在恢复期间,可能会有一段时间无法进行固件查找,在此短暂时间内,固件请求将失败。但是,时间至关重要,延迟驱动程序等待根文件系统获取固件会延迟设备功能的用户体验。为了支持这些要求,固件基础结构为大多数 API 调用自动在后台为设备驱动程序实现了一个固件缓存。
固件缓存使在设备驱动程序的挂起和恢复回调期间使用某些固件 API 调用是安全的。这些 API 调用的用户无需自行缓存固件来处理系统恢复期间的固件丢失问题。
固件缓存的工作原理是在挂起之前请求固件并将其缓存在内存中。恢复时,使用固件 API 的设备驱动程序将立即访问固件,而无需等待根文件系统挂载或处理根文件系统挂载时可能发生的查找竞争问题。
有关固件缓存设置的一些实现细节
固件缓存是通过为每个使用除
request_firmware_into_buf()
之外的所有同步调用的设备添加一个 devres 条目来设置的。如果使用异步调用,则只有当
request_firmware_nowait()
的第二个参数(uevent)为 true 时,才会为设备设置固件缓存。当 uevent 为 true 时,如果未找到固件文件,它会请求通过 sysfs 回退机制将 kobject uevent 发送到用户空间以进行固件请求。如果根据上述两个标准确定需要固件缓存,则会通过为发出固件请求的设备添加 devres 条目来设置固件缓存。
固件 devres 条目在设备的整个生命周期内维护。这意味着即使你 release_firmware(),在从挂起状态恢复时仍将使用固件缓存。
当在挂起期间设置固件缓存时,回退机制的超时时间将暂时缩短至 10 秒,在设置缓存后,超时时间将恢复为你配置的旧值。
挂起时,任何挂起的非 uevent 固件请求都会被终止,以避免内核停顿,这是通过 kill_requests_without_uevent() 完成的。因此,需要非 uevent 的内核调用需要实现它们自己的固件缓存机制,但不得在挂起时使用固件 API。