[ipc/ipcdev.git] / qnx / src / ipc3x_dev / ti / syslink / ipc / hlos / knl / transports / virtio / VirtQueue.c
diff --git a/qnx/src/ipc3x_dev/ti/syslink/ipc/hlos/knl/transports/virtio/VirtQueue.c b/qnx/src/ipc3x_dev/ti/syslink/ipc/hlos/knl/transports/virtio/VirtQueue.c
index 7242423edc04590ef4454f54e4f5c162d8c2ebcb..54074f060133639934e9a81050069133e13e1816 100644 (file)
/*
- * 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"
#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
/* 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 */
/* Private arg from user */
void * arg;
+
+ /* Mutex to protect vrings from multi-thread access */
+ pthread_mutex_t mutex;
} VirtQueue_Object;
static UInt numQueues = 0;
*/
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);
}
{
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.
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);
numQueues++;
vq->procId = procId;
vq->intId = coreIntId[procId];
- vq->last_avail_idx = 0;
vq->arg = arg;
/* init the vring */
vq = NULL;
}
+ /* Initialize mutex */
+ pthread_mutex_init(&vq->mutex, NULL);
+
return (vq);
}