Path: blob/master/drivers/base/firmware_loader/firmware.h
26428 views
/* SPDX-License-Identifier: GPL-2.0 */1#ifndef __FIRMWARE_LOADER_H2#define __FIRMWARE_LOADER_H34#include <linux/bitops.h>5#include <linux/firmware.h>6#include <linux/types.h>7#include <linux/kref.h>8#include <linux/list.h>9#include <linux/completion.h>1011/**12* enum fw_opt - options to control firmware loading behaviour13*14* @FW_OPT_UEVENT: Enables the fallback mechanism to send a kobject uevent15* when the firmware is not found. Userspace is in charge to load the16* firmware using the sysfs loading facility.17* @FW_OPT_NOWAIT: Used to describe the firmware request is asynchronous.18* @FW_OPT_USERHELPER: Enable the fallback mechanism, in case the direct19* filesystem lookup fails at finding the firmware. For details refer to20* firmware_fallback_sysfs().21* @FW_OPT_NO_WARN: Quiet, avoid printing warning messages.22* @FW_OPT_NOCACHE: Disables firmware caching. Firmware caching is used to23* cache the firmware upon suspend, so that upon resume races against the24* firmware file lookup on storage is avoided. Used for calls where the25* file may be too big, or where the driver takes charge of its own26* firmware caching mechanism.27* @FW_OPT_NOFALLBACK_SYSFS: Disable the sysfs fallback mechanism. Takes28* precedence over &FW_OPT_UEVENT and &FW_OPT_USERHELPER.29* @FW_OPT_FALLBACK_PLATFORM: Enable fallback to device fw copy embedded in30* the platform's main firmware. If both this fallback and the sysfs31* fallback are enabled, then this fallback will be tried first.32* @FW_OPT_PARTIAL: Allow partial read of firmware instead of needing to read33* entire file.34*/35enum fw_opt {36FW_OPT_UEVENT = BIT(0),37FW_OPT_NOWAIT = BIT(1),38FW_OPT_USERHELPER = BIT(2),39FW_OPT_NO_WARN = BIT(3),40FW_OPT_NOCACHE = BIT(4),41FW_OPT_NOFALLBACK_SYSFS = BIT(5),42FW_OPT_FALLBACK_PLATFORM = BIT(6),43FW_OPT_PARTIAL = BIT(7),44};4546enum fw_status {47FW_STATUS_UNKNOWN,48FW_STATUS_LOADING,49FW_STATUS_DONE,50FW_STATUS_ABORTED,51};5253/*54* Concurrent request_firmware() for the same firmware need to be55* serialized. struct fw_state is simple state machine which hold the56* state of the firmware loading.57*/58struct fw_state {59struct completion completion;60enum fw_status status;61};6263struct fw_priv {64struct kref ref;65struct list_head list;66struct firmware_cache *fwc;67struct fw_state fw_st;68void *data;69size_t size;70size_t allocated_size;71size_t offset;72u32 opt_flags;73#ifdef CONFIG_FW_LOADER_PAGED_BUF74bool is_paged_buf;75struct page **pages;76int nr_pages;77int page_array_size;78#endif79#ifdef CONFIG_FW_LOADER_USER_HELPER80bool need_uevent;81struct list_head pending_list;82#endif83const char *fw_name;84};8586extern struct mutex fw_lock;87extern struct firmware_cache fw_cache;88extern bool fw_load_abort_all;8990static inline bool __fw_state_check(struct fw_priv *fw_priv,91enum fw_status status)92{93struct fw_state *fw_st = &fw_priv->fw_st;9495return fw_st->status == status;96}9798static inline int __fw_state_wait_common(struct fw_priv *fw_priv, long timeout)99{100struct fw_state *fw_st = &fw_priv->fw_st;101long ret;102103ret = wait_for_completion_killable_timeout(&fw_st->completion, timeout);104if (ret != 0 && fw_st->status == FW_STATUS_ABORTED)105return -ENOENT;106if (!ret)107return -ETIMEDOUT;108109return ret < 0 ? ret : 0;110}111112static inline void __fw_state_set(struct fw_priv *fw_priv,113enum fw_status status)114{115struct fw_state *fw_st = &fw_priv->fw_st;116117WRITE_ONCE(fw_st->status, status);118119if (status == FW_STATUS_DONE || status == FW_STATUS_ABORTED) {120#ifdef CONFIG_FW_LOADER_USER_HELPER121/*122* Doing this here ensures that the fw_priv is deleted from123* the pending list in all abort/done paths.124*/125list_del_init(&fw_priv->pending_list);126#endif127complete_all(&fw_st->completion);128}129}130131static inline void fw_state_aborted(struct fw_priv *fw_priv)132{133__fw_state_set(fw_priv, FW_STATUS_ABORTED);134}135136static inline bool fw_state_is_aborted(struct fw_priv *fw_priv)137{138return __fw_state_check(fw_priv, FW_STATUS_ABORTED);139}140141static inline void fw_state_start(struct fw_priv *fw_priv)142{143__fw_state_set(fw_priv, FW_STATUS_LOADING);144}145146static inline void fw_state_done(struct fw_priv *fw_priv)147{148__fw_state_set(fw_priv, FW_STATUS_DONE);149}150151static inline bool fw_state_is_done(struct fw_priv *fw_priv)152{153return __fw_state_check(fw_priv, FW_STATUS_DONE);154}155156static inline bool fw_state_is_loading(struct fw_priv *fw_priv)157{158return __fw_state_check(fw_priv, FW_STATUS_LOADING);159}160161int alloc_lookup_fw_priv(const char *fw_name, struct firmware_cache *fwc,162struct fw_priv **fw_priv, void *dbuf, size_t size,163size_t offset, u32 opt_flags);164int assign_fw(struct firmware *fw, struct device *device);165void free_fw_priv(struct fw_priv *fw_priv);166void fw_state_init(struct fw_priv *fw_priv);167168#ifdef CONFIG_FW_LOADER169bool firmware_is_builtin(const struct firmware *fw);170bool firmware_request_builtin_buf(struct firmware *fw, const char *name,171void *buf, size_t size);172#else /* module case */173static inline bool firmware_is_builtin(const struct firmware *fw)174{175return false;176}177static inline bool firmware_request_builtin_buf(struct firmware *fw,178const char *name,179void *buf, size_t size)180{181return false;182}183#endif184185#ifdef CONFIG_FW_LOADER_PAGED_BUF186void fw_free_paged_buf(struct fw_priv *fw_priv);187int fw_grow_paged_buf(struct fw_priv *fw_priv, int pages_needed);188int fw_map_paged_buf(struct fw_priv *fw_priv);189bool fw_is_paged_buf(struct fw_priv *fw_priv);190#else191static inline void fw_free_paged_buf(struct fw_priv *fw_priv) {}192static inline int fw_grow_paged_buf(struct fw_priv *fw_priv, int pages_needed) { return -ENXIO; }193static inline int fw_map_paged_buf(struct fw_priv *fw_priv) { return -ENXIO; }194static inline bool fw_is_paged_buf(struct fw_priv *fw_priv) { return false; }195#endif196197#endif /* __FIRMWARE_LOADER_H */198199200