Skip to content

Commit 5d47ec0

Browse files
anderssongregkh
authored andcommitted
firmware: Correct handling of fw_state_wait() return value
When request_firmware() finds an already open firmware object it will wait for that object to become fully loaded and then check the status. As __fw_state_wait_common() succeeds the timeout value returned will be truncated in _request_firmware_prepare() and interpreted as -EPERM. Prior to "firmware: do not use fw_lock for fw_state protection" the code did test if we where in the "done" state before sleeping, causing this particular code path to succeed, in some cases. As the callers are interested in the result of the wait and not the remaining timeout the return value of __fw_state_wait_common() is changed to signal "done" or "error", which simplifies the logic in _request_firmware_load() as well. Fixes: 5b02962 ("firmware: do not use fw_lock for fw_state protection") Signed-off-by: Bjorn Andersson <[email protected]> Reviewed-by: Daniel Wagner <[email protected]> Acked-by: Luis R. Rodriguez <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 64df114 commit 5d47ec0

File tree

1 file changed

+6
-7
lines changed

1 file changed

+6
-7
lines changed

drivers/base/firmware_class.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ static inline bool __fw_state_is_done(enum fw_status status)
127127
return status == FW_STATUS_DONE || status == FW_STATUS_ABORTED;
128128
}
129129

130-
static long __fw_state_wait_common(struct fw_state *fw_st, long timeout)
130+
static int __fw_state_wait_common(struct fw_state *fw_st, long timeout)
131131
{
132132
long ret;
133133

@@ -136,8 +136,10 @@ static long __fw_state_wait_common(struct fw_state *fw_st, long timeout)
136136
timeout);
137137
if (ret != 0 && fw_st->status == FW_STATUS_ABORTED)
138138
return -ENOENT;
139+
if (!ret)
140+
return -ETIMEDOUT;
139141

140-
return ret;
142+
return ret < 0 ? ret : 0;
141143
}
142144

143145
static void __fw_state_set(struct fw_state *fw_st,
@@ -1017,14 +1019,11 @@ static int _request_firmware_load(struct firmware_priv *fw_priv,
10171019
timeout = MAX_JIFFY_OFFSET;
10181020
}
10191021

1020-
timeout = fw_state_wait_timeout(&buf->fw_st, timeout);
1021-
if (timeout == -ERESTARTSYS || !timeout) {
1022-
retval = timeout;
1022+
retval = fw_state_wait_timeout(&buf->fw_st, timeout);
1023+
if (retval < 0) {
10231024
mutex_lock(&fw_lock);
10241025
fw_load_abort(fw_priv);
10251026
mutex_unlock(&fw_lock);
1026-
} else if (timeout > 0) {
1027-
retval = 0;
10281027
}
10291028

10301029
if (fw_state_is_aborted(&buf->fw_st))

0 commit comments

Comments
 (0)