]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - ipc/ipcdev.git/blobdiff - qnx/src/ipc3x_dev/ti/syslink/ipc/hlos/knl/transports/virtio/VirtQueue.c
Merge branch '3.30' into ipc-next
[ipc/ipcdev.git] / qnx / src / ipc3x_dev / ti / syslink / ipc / hlos / knl / transports / virtio / VirtQueue.c
index 7242423edc04590ef4454f54e4f5c162d8c2ebcb..54074f060133639934e9a81050069133e13e1816 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Texas Instruments Incorporated
+ * Copyright (c) 2011-2015, Texas Instruments Incorporated
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 #include <ti/syslink/utils/Memory.h>
 #include <ti/syslink/utils/Trace.h>
 
-//#include <ti/sysbios/hal/Hwi.h>
-//#include <ti/sysbios/knl/Semaphore.h>
-//#include <ti/sysbios/knl/Clock.h>
-//#include <ti/sysbios/BIOS.h>
-//#include <ti/sysbios/hal/Cache.h>
-
 #include <_ArchIpcInt.h>
 #include <ArchIpcInt.h>
 #include "VirtQueue.h"
@@ -75,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
@@ -92,10 +87,7 @@ typedef struct VirtQueue_Object {
     /* Number of free buffers */
     UInt16                  num_free;
 
-    /* Last available index; updated by VirtQueue_getAvailBuf */
-    UInt16                  last_avail_idx;
-
-    /* Last available index; updated by VirtQueue_addUsedBuf */
+    /* Last available index; updated by VirtQueue_getUsedBuf */
     UInt16                  last_used_idx;
 
     /* Will eventually be used to kick remote processor */
@@ -112,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;
@@ -147,54 +142,22 @@ 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",
             vq->procId, vq->id);
 
-#if defined (SYSLINK_USE_IPU_PM)
+#if defined (IPC_USE_IPU_PM)
     ipu_pm_restore_ctx(vq->procId);
 #endif
     ArchIpcInt_sendInterrupt(vq->procId, vq->intId, vq->id);
 }
 
-/*!
- * ======== VirtQueue_addUsedBuf ========
- */
-Int VirtQueue_addUsedBuf(VirtQueue_Handle vq, Int16 head, UInt32 len)
-{
-    struct vring_used_elem *used;
-    Int status = 0;
-
-    if ((head > vq->vring.num) || (head < 0)) {
-        status = -1;
-        GT_setFailureReason (curTrace,
-                             GT_4CLASS,
-                             "VirtQueue_addUsedBuf",
-                             status,
-                             "head is invalid!");
-    }
-    else {
-        /*
-         * The virtqueue contains a ring of used buffers.  Get a pointer to the
-         * next entry in that used ring.
-         */
-        used = &vq->vring.used->ring[vq->vring.used->idx % vq->vring.num];
-        used->id = head;
-        used->len = len;
-
-        vq->vring.used->idx++;
-    }
-
-    return status;
-}
-
 /*!
  * ======== VirtQueue_addUsedBufAddr ========
  */
@@ -238,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,
@@ -257,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);
 }
 
@@ -270,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.
 
@@ -285,38 +265,7 @@ Int16 VirtQueue_getUsedBuf(VirtQueue_Object *vq, Void **buf)
     vq->last_used_idx++;
     vq->num_free++;
 
-    *buf = mapPAtoVA(vq, vq->vring.desc[head].addr);
-
-    return (head);
-}
-
-/*!
- * ======== VirtQueue_getAvailBuf ========
- */
-Int16 VirtQueue_getAvailBuf(VirtQueue_Handle vq, Void **buf)
-{
-    UInt16 head;
-
-    GT_6trace(curTrace, GT_2CLASS, "getAvailBuf vq: 0x%x %d %d %d 0x%x 0x%x",
-        (IArg)vq, vq->last_avail_idx, vq->vring.avail->idx, vq->vring.num,
-        (IArg)&vq->vring.avail, (IArg)vq->vring.avail);
-
-    /* There's nothing available? */
-    if (vq->last_avail_idx == vq->vring.avail->idx) {
-        /* We need to know about added buffers */
-        vq->vring.used->flags &= ~VRING_USED_F_NO_NOTIFY;
-
-        return (-1);
-    }
-
-    /* No need to know be kicked about added buffers anymore */
-    vq->vring.used->flags |= VRING_USED_F_NO_NOTIFY;
-
-    /*
-     * Grab the next descriptor number they're advertising, and increment
-     * the index we've seen.
-     */
-    head = vq->vring.avail->ring[vq->last_avail_idx++ % vq->vring.num];
+    pthread_mutex_unlock(&vq->mutex);
 
     *buf = mapPAtoVA(vq, vq->vring.desc[head].addr);
 
@@ -432,7 +381,6 @@ VirtQueue_Handle VirtQueue_create (VirtQueue_callback callback, UInt16 procId,
     numQueues++;
     vq->procId = procId;
     vq->intId = coreIntId[procId];
-    vq->last_avail_idx = 0;
     vq->arg = arg;
 
     /* init the vring */
@@ -459,6 +407,9 @@ VirtQueue_Handle VirtQueue_create (VirtQueue_callback callback, UInt16 procId,
         vq = NULL;
     }
 
+    /* Initialize mutex */
+    pthread_mutex_init(&vq->mutex, NULL);
+
     return (vq);
 }