|
@@ -153,28 +153,27 @@ static void __fw_state_set(struct fw_state *fw_st,
|
|
|
__fw_state_set(fw_st, FW_STATUS_LOADING)
|
|
|
#define fw_state_done(fw_st) \
|
|
|
__fw_state_set(fw_st, FW_STATUS_DONE)
|
|
|
+#define fw_state_aborted(fw_st) \
|
|
|
+ __fw_state_set(fw_st, FW_STATUS_ABORTED)
|
|
|
#define fw_state_wait(fw_st) \
|
|
|
__fw_state_wait_common(fw_st, MAX_SCHEDULE_TIMEOUT)
|
|
|
|
|
|
-#ifndef CONFIG_FW_LOADER_USER_HELPER
|
|
|
-
|
|
|
-#define fw_state_is_aborted(fw_st) false
|
|
|
-
|
|
|
-#else /* CONFIG_FW_LOADER_USER_HELPER */
|
|
|
-
|
|
|
static int __fw_state_check(struct fw_state *fw_st, enum fw_status status)
|
|
|
{
|
|
|
return fw_st->status == status;
|
|
|
}
|
|
|
|
|
|
+#define fw_state_is_aborted(fw_st) \
|
|
|
+ __fw_state_check(fw_st, FW_STATUS_ABORTED)
|
|
|
+
|
|
|
+#ifdef CONFIG_FW_LOADER_USER_HELPER
|
|
|
+
|
|
|
#define fw_state_aborted(fw_st) \
|
|
|
__fw_state_set(fw_st, FW_STATUS_ABORTED)
|
|
|
#define fw_state_is_done(fw_st) \
|
|
|
__fw_state_check(fw_st, FW_STATUS_DONE)
|
|
|
#define fw_state_is_loading(fw_st) \
|
|
|
__fw_state_check(fw_st, FW_STATUS_LOADING)
|
|
|
-#define fw_state_is_aborted(fw_st) \
|
|
|
- __fw_state_check(fw_st, FW_STATUS_ABORTED)
|
|
|
#define fw_state_wait_timeout(fw_st, timeout) \
|
|
|
__fw_state_wait_common(fw_st, timeout)
|
|
|
|
|
@@ -1198,6 +1197,28 @@ _request_firmware_prepare(struct firmware **firmware_p, const char *name,
|
|
|
return 1; /* need to load */
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * Batched requests need only one wake, we need to do this step last due to the
|
|
|
+ * fallback mechanism. The buf is protected with kref_get(), and it won't be
|
|
|
+ * released until the last user calls release_firmware().
|
|
|
+ *
|
|
|
+ * Failed batched requests are possible as well, in such cases we just share
|
|
|
+ * the struct firmware_buf and won't release it until all requests are woken
|
|
|
+ * and have gone through this same path.
|
|
|
+ */
|
|
|
+static void fw_abort_batch_reqs(struct firmware *fw)
|
|
|
+{
|
|
|
+ struct firmware_buf *buf;
|
|
|
+
|
|
|
+ /* Loaded directly? */
|
|
|
+ if (!fw || !fw->priv)
|
|
|
+ return;
|
|
|
+
|
|
|
+ buf = fw->priv;
|
|
|
+ if (!fw_state_is_aborted(&buf->fw_st))
|
|
|
+ fw_state_aborted(&buf->fw_st);
|
|
|
+}
|
|
|
+
|
|
|
/* called from request_firmware() and request_firmware_work_func() */
|
|
|
static int
|
|
|
_request_firmware(const struct firmware **firmware_p, const char *name,
|
|
@@ -1241,6 +1262,7 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
|
|
|
|
|
|
out:
|
|
|
if (ret < 0) {
|
|
|
+ fw_abort_batch_reqs(fw);
|
|
|
release_firmware(fw);
|
|
|
fw = NULL;
|
|
|
}
|