30
30
#include <linux/syscore_ops.h>
31
31
#include <linux/reboot.h>
32
32
#include <linux/security.h>
33
- #include <linux/swait.h>
34
33
35
34
#include <generated/utsrelease.h>
36
35
@@ -112,13 +111,13 @@ static inline long firmware_loading_timeout(void)
112
111
* state of the firmware loading.
113
112
*/
114
113
struct fw_state {
115
- struct swait_queue_head wq ;
114
+ struct completion completion ;
116
115
enum fw_status status ;
117
116
};
118
117
119
118
static void fw_state_init (struct fw_state * fw_st )
120
119
{
121
- init_swait_queue_head (& fw_st -> wq );
120
+ init_completion (& fw_st -> completion );
122
121
fw_st -> status = FW_STATUS_UNKNOWN ;
123
122
}
124
123
@@ -131,9 +130,7 @@ static int __fw_state_wait_common(struct fw_state *fw_st, long timeout)
131
130
{
132
131
long ret ;
133
132
134
- ret = swait_event_interruptible_timeout (fw_st -> wq ,
135
- __fw_state_is_done (READ_ONCE (fw_st -> status )),
136
- timeout );
133
+ ret = wait_for_completion_killable_timeout (& fw_st -> completion , timeout );
137
134
if (ret != 0 && fw_st -> status == FW_STATUS_ABORTED )
138
135
return - ENOENT ;
139
136
if (!ret )
@@ -148,35 +145,34 @@ static void __fw_state_set(struct fw_state *fw_st,
148
145
WRITE_ONCE (fw_st -> status , status );
149
146
150
147
if (status == FW_STATUS_DONE || status == FW_STATUS_ABORTED )
151
- swake_up (& fw_st -> wq );
148
+ complete_all (& fw_st -> completion );
152
149
}
153
150
154
151
#define fw_state_start (fw_st ) \
155
152
__fw_state_set(fw_st, FW_STATUS_LOADING)
156
153
#define fw_state_done (fw_st ) \
157
154
__fw_state_set(fw_st, FW_STATUS_DONE)
155
+ #define fw_state_aborted (fw_st ) \
156
+ __fw_state_set(fw_st, FW_STATUS_ABORTED)
158
157
#define fw_state_wait (fw_st ) \
159
158
__fw_state_wait_common(fw_st, MAX_SCHEDULE_TIMEOUT)
160
159
161
- #ifndef CONFIG_FW_LOADER_USER_HELPER
162
-
163
- #define fw_state_is_aborted (fw_st ) false
164
-
165
- #else /* CONFIG_FW_LOADER_USER_HELPER */
166
-
167
160
static int __fw_state_check (struct fw_state * fw_st , enum fw_status status )
168
161
{
169
162
return fw_st -> status == status ;
170
163
}
171
164
165
+ #define fw_state_is_aborted (fw_st ) \
166
+ __fw_state_check(fw_st, FW_STATUS_ABORTED)
167
+
168
+ #ifdef CONFIG_FW_LOADER_USER_HELPER
169
+
172
170
#define fw_state_aborted (fw_st ) \
173
171
__fw_state_set(fw_st, FW_STATUS_ABORTED)
174
172
#define fw_state_is_done (fw_st ) \
175
173
__fw_state_check(fw_st, FW_STATUS_DONE)
176
174
#define fw_state_is_loading (fw_st ) \
177
175
__fw_state_check(fw_st, FW_STATUS_LOADING)
178
- #define fw_state_is_aborted (fw_st ) \
179
- __fw_state_check(fw_st, FW_STATUS_ABORTED)
180
176
#define fw_state_wait_timeout (fw_st , timeout ) \
181
177
__fw_state_wait_common(fw_st, timeout)
182
178
@@ -1200,6 +1196,28 @@ _request_firmware_prepare(struct firmware **firmware_p, const char *name,
1200
1196
return 1 ; /* need to load */
1201
1197
}
1202
1198
1199
+ /*
1200
+ * Batched requests need only one wake, we need to do this step last due to the
1201
+ * fallback mechanism. The buf is protected with kref_get(), and it won't be
1202
+ * released until the last user calls release_firmware().
1203
+ *
1204
+ * Failed batched requests are possible as well, in such cases we just share
1205
+ * the struct firmware_buf and won't release it until all requests are woken
1206
+ * and have gone through this same path.
1207
+ */
1208
+ static void fw_abort_batch_reqs (struct firmware * fw )
1209
+ {
1210
+ struct firmware_buf * buf ;
1211
+
1212
+ /* Loaded directly? */
1213
+ if (!fw || !fw -> priv )
1214
+ return ;
1215
+
1216
+ buf = fw -> priv ;
1217
+ if (!fw_state_is_aborted (& buf -> fw_st ))
1218
+ fw_state_aborted (& buf -> fw_st );
1219
+ }
1220
+
1203
1221
/* called from request_firmware() and request_firmware_work_func() */
1204
1222
static int
1205
1223
_request_firmware (const struct firmware * * firmware_p , const char * name ,
@@ -1243,6 +1261,7 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
1243
1261
1244
1262
out :
1245
1263
if (ret < 0 ) {
1264
+ fw_abort_batch_reqs (fw );
1246
1265
release_firmware (fw );
1247
1266
fw = NULL ;
1248
1267
}
0 commit comments