Merge branch '3.30' into ipc-next
[ipc/ipcdev.git] / qnx / src / ipc3x_dev / ti / syslink / ipc / hlos / knl / transports / virtio / VirtQueue.c
index d74621dd13063f7673aadea36e2e2aeda1f6a560..54074f060133639934e9a81050069133e13e1816 100644 (file)
@@ -69,6 +69,7 @@
 #include "virtio_ring.h"
 #include "_rpmsg.h"
 #include <ipu_pm.h>
+#include <pthread.h>
 
 /* Used for defining the size of the virtqueue registry */
 #define NUM_QUEUES                      2
@@ -103,6 +104,9 @@ typedef struct VirtQueue_Object {
 
     /* Private arg from user */
     void *                  arg;
+
+    /* Mutex to protect vrings from multi-thread access */
+    pthread_mutex_t         mutex;
 } VirtQueue_Object;
 
 static UInt numQueues = 0;
@@ -138,12 +142,11 @@ Void VirtQueue_cb(Void *buf, VirtQueue_Handle vq)
  */
 Void VirtQueue_kick(VirtQueue_Handle vq)
 {
-    /* For now, simply interrupt remote processor */
-    if (vq->vring.used->flags & VRING_USED_F_NO_NOTIFY) {
-        GT_0trace(curTrace, GT_3CLASS,
-                "VirtQueue_kick: no kick because of VRING_USED_F_NO_NOTIFY");
-        return;
-    }
+    /*
+     * We need to expose available array entries before sending an
+     * interrupt.
+     */
+    asm("   DSB ST");
 
     GT_2trace(curTrace, GT_2CLASS,
             "VirtQueue_kick: Sending interrupt to proc %d with payload 0x%x",
@@ -198,6 +201,8 @@ Int VirtQueue_addAvailBuf(VirtQueue_Handle vq, Void *buf, UInt32 len, Int16 head
 {
     UInt16 avail;
 
+    pthread_mutex_lock(&vq->mutex);
+
     if (vq->num_free == 0) {
         /* There's no more space */
         GT_setFailureReason (curTrace,
@@ -217,9 +222,17 @@ Int VirtQueue_addAvailBuf(VirtQueue_Handle vq, Void *buf, UInt32 len, Int16 head
         vq->vring.desc[head].len = len;
         vq->vring.desc[head].flags = 0;
 
+        /*
+         * Descriptors and available array need to be set before we expose the
+         * new available array entries.
+         */
+        asm("   DMB ST");
+
         vq->vring.avail->idx++;
     }
 
+    pthread_mutex_unlock(&vq->mutex);
+
     return (vq->num_free);
 }
 
@@ -230,14 +243,21 @@ Int16 VirtQueue_getUsedBuf(VirtQueue_Object *vq, Void **buf)
 {
     UInt16 head;
 
+    pthread_mutex_lock(&vq->mutex);
+
     /* There's nothing available? */
     if (vq->last_used_idx == vq->vring.used->idx) {
         /* We need to know about added buffers */
         vq->vring.avail->flags &= ~VRING_AVAIL_F_NO_INTERRUPT;
 
+        pthread_mutex_unlock(&vq->mutex);
+
         return (-1);
     }
 
+    /* Only get used array entries after they have been exposed. */
+    asm("   DMB");
+
     /* No need to know be kicked about added buffers anymore */
     //vq->vring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT; // disabling for now, since there seems to be a race condition where an M3->A9 message is not detected because the interrupt isn't sent.
 
@@ -245,6 +265,8 @@ Int16 VirtQueue_getUsedBuf(VirtQueue_Object *vq, Void **buf)
     vq->last_used_idx++;
     vq->num_free++;
 
+    pthread_mutex_unlock(&vq->mutex);
+
     *buf = mapPAtoVA(vq, vq->vring.desc[head].addr);
 
     return (head);
@@ -385,6 +407,9 @@ VirtQueue_Handle VirtQueue_create (VirtQueue_callback callback, UInt16 procId,
         vq = NULL;
     }
 
+    /* Initialize mutex */
+    pthread_mutex_init(&vq->mutex, NULL);
+
     return (vq);
 }