VirtQueue: OMAP5: Poll for VDEV status in VirtQueue_startup()
authorG Anthony <a0783926@ti.com>
Tue, 6 Aug 2013 13:29:58 +0000 (06:29 -0700)
committerRamsey Harris <ramsey@ti.com>
Tue, 6 Aug 2013 18:05:45 +0000 (11:05 -0700)
This resolves a race condition where the first slave RPMSG send would block
in a non-task context on a Semaphore_pend(), when the slave loads faster than
than the host can prime the send buffers in the vring to the host.

This patch implements the solution for OMAP5 separately.

Signed-off-by: G Anthony <a0783926@ti.com>
packages/ti/ipc/family/omap54xx/VirtQueue.c

index 7e722d0d44086c464718296fa1bfa6b65488a5e4..c055ada73ba895e589029bb95bfd5877a942ed79 100644 (file)
 #include <ti/pm/IpcPower.h>
 #include <string.h>
 
+#include <ti/ipc/remoteproc/Resource.h>
+#include <ti/ipc/remoteproc/rsc_types.h>
 #include <ti/ipc/rpmsg/_VirtQueue.h>
 
 #include "InterruptProxy.h"
 #include "VirtQueue.h"
 
 
+/*
+ *  The following three VIRTIO_* defines must match those in
+ *  <Linux_kernel>/include/uapi/linux/virtio_config.h
+ */
+#define VIRTIO_CONFIG_S_ACKNOWLEDGE     1
+#define VIRTIO_CONFIG_S_DRIVER          2
+#define VIRTIO_CONFIG_S_DRIVER_OK       4
+
+#define VRING_BUFS_PRIMED  (VIRTIO_CONFIG_S_ACKNOWLEDGE | \
+                            VIRTIO_CONFIG_S_DRIVER | VIRTIO_CONFIG_S_DRIVER_OK)
+
 /* Used for defining the size of the virtqueue registry */
 #define NUM_QUEUES              4
 
@@ -620,7 +633,22 @@ Void VirtQueue_startup()
     }
 #endif
 
+    /*
+     * Wait for HLOS (Virtio device) to indicate that priming of host's receive
+     * buffers is complete, indicating that host is ready to send.
+     *
+     * Though this is a Linux Virtio configuration status, it must be
+     * implemented by each non-Linux HLOS as well.
+     */
+    Log_print1(Diags_USER1, "VirtQueue_startup: VDEV status: 0x%x\n",
+              Resource_getVdevStatus(VIRTIO_ID_RPMSG));
+    Log_print0(Diags_USER1, "VirtQueue_startup: Polling VDEV status...\n");
+    while (Resource_getVdevStatus(VIRTIO_ID_RPMSG) != VRING_BUFS_PRIMED);
+    Log_print1(Diags_USER1, "VirtQueue_startup: VDEV status: 0x%x\n",
+              Resource_getVdevStatus(VIRTIO_ID_RPMSG));
+
     InterruptProxy_intRegister(VirtQueue_isr);
+    Log_print0(Diags_USER1, "Passed VirtQueue_startup\n");
 }
 
 /*!