]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/commitdiff
vchiq_arm: Add completion records under the mutex
authorPhil Elwell <phil@raspberrypi.org>
Thu, 21 Apr 2016 12:49:32 +0000 (13:49 +0100)
committerKleber Sacilotto de Souza <kleber.souza@canonical.com>
Tue, 19 Sep 2017 10:07:47 +0000 (12:07 +0200)
An issue was observed when flushing openmax components
which generate a large number of messages returning
buffers to host.

We occasionally found a duplicate message from 16
messages prior, resulting in a buffer returned twice.

While only one thread adds completions, without the
mutex you don't get the protection of the automatic
memory barrier you get with synchronisation objects.

Signed-off-by: Phil Elwell <phil@raspberrypi.org>
drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c

index 4a218026cddb253c54d06c2fd9d9b034ac2dddc4..6611b0c8fe2de19c0dae9bf2168b5c42b027f7e3 100644 (file)
@@ -210,6 +210,8 @@ add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason,
        VCHIQ_COMPLETION_DATA_T *completion;
        DEBUG_INITIALISE(g_state.local)
 
+       mutex_lock(&instance->completion_mutex);
+
        while (instance->completion_insert ==
                (instance->completion_remove + MAX_COMPLETIONS)) {
                /* Out of space - wait for the client */
@@ -217,11 +219,17 @@ add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason,
                vchiq_log_trace(vchiq_arm_log_level,
                        "add_completion - completion queue full");
                DEBUG_COUNT(COMPLETION_QUEUE_FULL_COUNT);
+
+               mutex_unlock(&instance->completion_mutex);
                if (down_interruptible(&instance->remove_event) != 0) {
                        vchiq_log_info(vchiq_arm_log_level,
                                "service_callback interrupted");
                        return VCHIQ_RETRY;
-               } else if (instance->closing) {
+               }
+
+               mutex_lock(&instance->completion_mutex);
+               if (instance->closing) {
+                       mutex_unlock(&instance->completion_mutex);
                        vchiq_log_info(vchiq_arm_log_level,
                                "service_callback closing");
                        return VCHIQ_SUCCESS;
@@ -254,8 +262,11 @@ add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason,
        if (reason == VCHIQ_MESSAGE_AVAILABLE)
                user_service->message_available_pos =
                        instance->completion_insert;
+
        instance->completion_insert++;
 
+       mutex_unlock(&instance->completion_mutex);
+
        up(&instance->insert_event);
 
        return VCHIQ_SUCCESS;