1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | #ifndef __FIRMWARE_LOADER_H |
3 | #define __FIRMWARE_LOADER_H |
4 | |
5 | #include <linux/bitops.h> |
6 | #include <linux/firmware.h> |
7 | #include <linux/types.h> |
8 | #include <linux/kref.h> |
9 | #include <linux/list.h> |
10 | #include <linux/completion.h> |
11 | |
12 | /** |
13 | * enum fw_opt - options to control firmware loading behaviour |
14 | * |
15 | * @FW_OPT_UEVENT: Enables the fallback mechanism to send a kobject uevent |
16 | * when the firmware is not found. Userspace is in charge to load the |
17 | * firmware using the sysfs loading facility. |
18 | * @FW_OPT_NOWAIT: Used to describe the firmware request is asynchronous. |
19 | * @FW_OPT_USERHELPER: Enable the fallback mechanism, in case the direct |
20 | * filesystem lookup fails at finding the firmware. For details refer to |
21 | * firmware_fallback_sysfs(). |
22 | * @FW_OPT_NO_WARN: Quiet, avoid printing warning messages. |
23 | * @FW_OPT_NOCACHE: Disables firmware caching. Firmware caching is used to |
24 | * cache the firmware upon suspend, so that upon resume races against the |
25 | * firmware file lookup on storage is avoided. Used for calls where the |
26 | * file may be too big, or where the driver takes charge of its own |
27 | * firmware caching mechanism. |
28 | * @FW_OPT_NOFALLBACK_SYSFS: Disable the sysfs fallback mechanism. Takes |
29 | * precedence over &FW_OPT_UEVENT and &FW_OPT_USERHELPER. |
30 | * @FW_OPT_FALLBACK_PLATFORM: Enable fallback to device fw copy embedded in |
31 | * the platform's main firmware. If both this fallback and the sysfs |
32 | * fallback are enabled, then this fallback will be tried first. |
33 | * @FW_OPT_PARTIAL: Allow partial read of firmware instead of needing to read |
34 | * entire file. |
35 | */ |
36 | enum fw_opt { |
37 | FW_OPT_UEVENT = BIT(0), |
38 | FW_OPT_NOWAIT = BIT(1), |
39 | FW_OPT_USERHELPER = BIT(2), |
40 | FW_OPT_NO_WARN = BIT(3), |
41 | FW_OPT_NOCACHE = BIT(4), |
42 | FW_OPT_NOFALLBACK_SYSFS = BIT(5), |
43 | FW_OPT_FALLBACK_PLATFORM = BIT(6), |
44 | FW_OPT_PARTIAL = BIT(7), |
45 | }; |
46 | |
47 | enum fw_status { |
48 | FW_STATUS_UNKNOWN, |
49 | FW_STATUS_LOADING, |
50 | FW_STATUS_DONE, |
51 | FW_STATUS_ABORTED, |
52 | }; |
53 | |
54 | /* |
55 | * Concurrent request_firmware() for the same firmware need to be |
56 | * serialized. struct fw_state is simple state machine which hold the |
57 | * state of the firmware loading. |
58 | */ |
59 | struct fw_state { |
60 | struct completion completion; |
61 | enum fw_status status; |
62 | }; |
63 | |
64 | struct fw_priv { |
65 | struct kref ref; |
66 | struct list_head list; |
67 | struct firmware_cache *fwc; |
68 | struct fw_state fw_st; |
69 | void *data; |
70 | size_t size; |
71 | size_t allocated_size; |
72 | size_t offset; |
73 | u32 opt_flags; |
74 | #ifdef CONFIG_FW_LOADER_PAGED_BUF |
75 | bool is_paged_buf; |
76 | struct page **pages; |
77 | int nr_pages; |
78 | int page_array_size; |
79 | #endif |
80 | #ifdef CONFIG_FW_LOADER_USER_HELPER |
81 | bool need_uevent; |
82 | struct list_head pending_list; |
83 | #endif |
84 | const char *fw_name; |
85 | }; |
86 | |
87 | extern struct mutex fw_lock; |
88 | extern struct firmware_cache fw_cache; |
89 | extern bool fw_load_abort_all; |
90 | |
91 | static inline bool __fw_state_check(struct fw_priv *fw_priv, |
92 | enum fw_status status) |
93 | { |
94 | struct fw_state *fw_st = &fw_priv->fw_st; |
95 | |
96 | return fw_st->status == status; |
97 | } |
98 | |
99 | static inline int __fw_state_wait_common(struct fw_priv *fw_priv, long timeout) |
100 | { |
101 | struct fw_state *fw_st = &fw_priv->fw_st; |
102 | long ret; |
103 | |
104 | ret = wait_for_completion_killable_timeout(x: &fw_st->completion, timeout); |
105 | if (ret != 0 && fw_st->status == FW_STATUS_ABORTED) |
106 | return -ENOENT; |
107 | if (!ret) |
108 | return -ETIMEDOUT; |
109 | |
110 | return ret < 0 ? ret : 0; |
111 | } |
112 | |
113 | static inline void __fw_state_set(struct fw_priv *fw_priv, |
114 | enum fw_status status) |
115 | { |
116 | struct fw_state *fw_st = &fw_priv->fw_st; |
117 | |
118 | WRITE_ONCE(fw_st->status, status); |
119 | |
120 | if (status == FW_STATUS_DONE || status == FW_STATUS_ABORTED) { |
121 | #ifdef CONFIG_FW_LOADER_USER_HELPER |
122 | /* |
123 | * Doing this here ensures that the fw_priv is deleted from |
124 | * the pending list in all abort/done paths. |
125 | */ |
126 | list_del_init(entry: &fw_priv->pending_list); |
127 | #endif |
128 | complete_all(&fw_st->completion); |
129 | } |
130 | } |
131 | |
132 | static inline void fw_state_aborted(struct fw_priv *fw_priv) |
133 | { |
134 | __fw_state_set(fw_priv, status: FW_STATUS_ABORTED); |
135 | } |
136 | |
137 | static inline bool fw_state_is_aborted(struct fw_priv *fw_priv) |
138 | { |
139 | return __fw_state_check(fw_priv, status: FW_STATUS_ABORTED); |
140 | } |
141 | |
142 | static inline void fw_state_start(struct fw_priv *fw_priv) |
143 | { |
144 | __fw_state_set(fw_priv, status: FW_STATUS_LOADING); |
145 | } |
146 | |
147 | static inline void fw_state_done(struct fw_priv *fw_priv) |
148 | { |
149 | __fw_state_set(fw_priv, status: FW_STATUS_DONE); |
150 | } |
151 | |
152 | static inline bool fw_state_is_done(struct fw_priv *fw_priv) |
153 | { |
154 | return __fw_state_check(fw_priv, status: FW_STATUS_DONE); |
155 | } |
156 | |
157 | static inline bool fw_state_is_loading(struct fw_priv *fw_priv) |
158 | { |
159 | return __fw_state_check(fw_priv, status: FW_STATUS_LOADING); |
160 | } |
161 | |
162 | int alloc_lookup_fw_priv(const char *fw_name, struct firmware_cache *fwc, |
163 | struct fw_priv **fw_priv, void *dbuf, size_t size, |
164 | size_t offset, u32 opt_flags); |
165 | int assign_fw(struct firmware *fw, struct device *device); |
166 | void free_fw_priv(struct fw_priv *fw_priv); |
167 | void fw_state_init(struct fw_priv *fw_priv); |
168 | |
169 | #ifdef CONFIG_FW_LOADER |
170 | bool firmware_is_builtin(const struct firmware *fw); |
171 | bool firmware_request_builtin_buf(struct firmware *fw, const char *name, |
172 | void *buf, size_t size); |
173 | #else /* module case */ |
174 | static inline bool firmware_is_builtin(const struct firmware *fw) |
175 | { |
176 | return false; |
177 | } |
178 | static inline bool firmware_request_builtin_buf(struct firmware *fw, |
179 | const char *name, |
180 | void *buf, size_t size) |
181 | { |
182 | return false; |
183 | } |
184 | #endif |
185 | |
186 | #ifdef CONFIG_FW_LOADER_PAGED_BUF |
187 | void fw_free_paged_buf(struct fw_priv *fw_priv); |
188 | int fw_grow_paged_buf(struct fw_priv *fw_priv, int pages_needed); |
189 | int fw_map_paged_buf(struct fw_priv *fw_priv); |
190 | bool fw_is_paged_buf(struct fw_priv *fw_priv); |
191 | #else |
192 | static inline void fw_free_paged_buf(struct fw_priv *fw_priv) {} |
193 | static inline int fw_grow_paged_buf(struct fw_priv *fw_priv, int pages_needed) { return -ENXIO; } |
194 | static inline int fw_map_paged_buf(struct fw_priv *fw_priv) { return -ENXIO; } |
195 | static inline bool fw_is_paged_buf(struct fw_priv *fw_priv) { return false; } |
196 | #endif |
197 | |
198 | #endif /* __FIRMWARE_LOADER_H */ |
199 | |