staging: vchiq_core: Bubble up wait_event_interruptible() return value
BugLink: https://bugs.launchpad.net/bugs/2085849 [ Upstream commit c22502cb84d4c963f754e6d943d3133cfa80ba97 ] wait_event_interruptible() returns if the condition evaluates to true it receives a signal. However, the current code always assume that the wait_event_interruptible() returns only when the event is fired. This should not be the case as wait_event_interruptible() can return on receiving a signal (with -ERESTARTSYS as return value). We should consider this and bubble up the return value of wait_event_interruptible() to exactly know if the wait has failed and error out. This will also help to properly stop kthreads in the subsequent patch. Meanwhile at it, remote_wait_event() is modified to return 0 on success, and an error code (from wait_event_interruptible()) on failure. The return value is now checked for remote_wait_event() calls. Signed-off-by: Umang Jain <umang.jain@ideasonboard.com> Tested-by: Stefan Wahren <wahrenst@gmx.net> Link: https://lore.kernel.org/r/20240703131052.597443-2-umang.jain@ideasonboard.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Manuel Diewald <manuel.diewald@canonical.com> Signed-off-by: Roxana Nicolescu <roxana.nicolescu@canonical.com>
This commit is contained in:
committed by
Mehmet Basaran
parent
69811809b0
commit
635fad3da5
@@ -503,16 +503,21 @@ remote_event_create(wait_queue_head_t *wq, struct remote_event *event)
|
||||
* routines where switched to the "interruptible" family of functions, as the
|
||||
* former was deemed unjustified and the use "killable" set all VCHIQ's
|
||||
* threads in D state.
|
||||
*
|
||||
* Returns: 0 on success, a negative error code on failure
|
||||
*/
|
||||
static inline int
|
||||
remote_event_wait(wait_queue_head_t *wq, struct remote_event *event)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!event->fired) {
|
||||
event->armed = 1;
|
||||
dsb(sy);
|
||||
if (wait_event_interruptible(*wq, event->fired)) {
|
||||
ret = wait_event_interruptible(*wq, event->fired);
|
||||
if (ret) {
|
||||
event->armed = 0;
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
event->armed = 0;
|
||||
/* Ensure that the peer sees that we are not waiting (armed == 0). */
|
||||
@@ -520,7 +525,7 @@ remote_event_wait(wait_queue_head_t *wq, struct remote_event *event)
|
||||
}
|
||||
|
||||
event->fired = 0;
|
||||
return 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1141,6 +1146,7 @@ queue_message_sync(struct vchiq_state *state, struct vchiq_service *service,
|
||||
struct vchiq_header *header;
|
||||
ssize_t callback_result;
|
||||
int svc_fourcc;
|
||||
int ret;
|
||||
|
||||
local = state->local;
|
||||
|
||||
@@ -1148,7 +1154,9 @@ queue_message_sync(struct vchiq_state *state, struct vchiq_service *service,
|
||||
mutex_lock_killable(&state->sync_mutex))
|
||||
return -EAGAIN;
|
||||
|
||||
remote_event_wait(&state->sync_release_event, &local->sync_release);
|
||||
ret = remote_event_wait(&state->sync_release_event, &local->sync_release);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Ensure that reads don't overtake the remote_event_wait. */
|
||||
rmb();
|
||||
@@ -1933,13 +1941,16 @@ slot_handler_func(void *v)
|
||||
{
|
||||
struct vchiq_state *state = v;
|
||||
struct vchiq_shared_state *local = state->local;
|
||||
int ret;
|
||||
|
||||
DEBUG_INITIALISE(local);
|
||||
|
||||
while (1) {
|
||||
DEBUG_COUNT(SLOT_HANDLER_COUNT);
|
||||
DEBUG_TRACE(SLOT_HANDLER_LINE);
|
||||
remote_event_wait(&state->trigger_event, &local->trigger);
|
||||
ret = remote_event_wait(&state->trigger_event, &local->trigger);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Ensure that reads don't overtake the remote_event_wait. */
|
||||
rmb();
|
||||
@@ -1970,6 +1981,7 @@ recycle_func(void *v)
|
||||
struct vchiq_shared_state *local = state->local;
|
||||
u32 *found;
|
||||
size_t length;
|
||||
int ret;
|
||||
|
||||
length = sizeof(*found) * BITSET_SIZE(VCHIQ_MAX_SERVICES);
|
||||
|
||||
@@ -1979,7 +1991,9 @@ recycle_func(void *v)
|
||||
return -ENOMEM;
|
||||
|
||||
while (1) {
|
||||
remote_event_wait(&state->recycle_event, &local->recycle);
|
||||
ret = remote_event_wait(&state->recycle_event, &local->recycle);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
process_free_queue(state, found, length);
|
||||
}
|
||||
@@ -1996,6 +2010,7 @@ sync_func(void *v)
|
||||
(struct vchiq_header *)SLOT_DATA_FROM_INDEX(state,
|
||||
state->remote->slot_sync);
|
||||
int svc_fourcc;
|
||||
int ret;
|
||||
|
||||
while (1) {
|
||||
struct vchiq_service *service;
|
||||
@@ -2003,7 +2018,9 @@ sync_func(void *v)
|
||||
int type;
|
||||
unsigned int localport, remoteport;
|
||||
|
||||
remote_event_wait(&state->sync_trigger_event, &local->sync_trigger);
|
||||
ret = remote_event_wait(&state->sync_trigger_event, &local->sync_trigger);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Ensure that reads don't overtake the remote_event_wait. */
|
||||
rmb();
|
||||
|
||||
Reference in New Issue
Block a user