diff options
author | Phil Elwell <phil@raspberrypi.org> | 2017-01-17 20:56:12 +0000 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-01-19 11:08:57 +0100 |
commit | 72ed1db4cd4eb8bd7e46b5b6f9dd56b1b36fe660 (patch) | |
tree | f9efac3a4f512e1a5f0c7bf637d9e1c31d81d2f2 /drivers/staging | |
parent | c599a22e60f95f405fe6cb9f5b25d88fd7e59a7f (diff) |
staging: vchiq_arm: Fix unlocked access to dequeue_pending
The dequeue_pending flag wasn't protected by a spinlock in the
service_callback. So fix this to make it safe.
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging')
-rw-r--r-- | drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 13 |
1 files changed, 8 insertions, 5 deletions
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c index 0525211bcd65..4f024fab4f84 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c @@ -279,6 +279,7 @@ service_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header, USER_SERVICE_T *user_service; VCHIQ_SERVICE_T *service; VCHIQ_INSTANCE_T instance; + bool skip_completion = false; DEBUG_INITIALISE(g_state.local) DEBUG_TRACE(SERVICE_CALLBACK_LINE); @@ -345,9 +346,6 @@ service_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header, user_service->msg_queue[user_service->msg_insert & (MSG_QUEUE_SIZE - 1)] = header; user_service->msg_insert++; - spin_unlock(&msg_queue_spinlock); - - up(&user_service->insert_event); /* If there is a thread waiting in DEQUEUE_MESSAGE, or if ** there is a MESSAGE_AVAILABLE in the completion queue then @@ -356,15 +354,20 @@ service_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header, if (((user_service->message_available_pos - instance->completion_remove) >= 0) || user_service->dequeue_pending) { - DEBUG_TRACE(SERVICE_CALLBACK_LINE); user_service->dequeue_pending = 0; - return VCHIQ_SUCCESS; + skip_completion = true; } + spin_unlock(&msg_queue_spinlock); + up(&user_service->insert_event); + header = NULL; } DEBUG_TRACE(SERVICE_CALLBACK_LINE); + if (skip_completion) + return VCHIQ_SUCCESS; + return add_completion(instance, reason, header, user_service, bulk_userdata); } |