]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - ipc/ipcdev.git/blobdiff - packages/ti/ipc/family/vayu/VirtQueue.c
DRA7XX: Remove unnecessary rpmsg-related code
[ipc/ipcdev.git] / packages / ti / ipc / family / vayu / VirtQueue.c
index 438e1af4f4cc007e4d91d8b1ad2a837be37a3daf..5b11e7cc6f33e10ed87cf01ee7f8205275addc99 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2013, Texas Instruments Incorporated
+ * Copyright (c) 2011-2014, Texas Instruments Incorporated
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  *
  */
 
+/* this define must precede inclusion of any xdc header file */
+#define Registry_CURDESC ti_ipc_family_vayu__Desc
+#define MODULE_NAME "ti.ipc.family.vayu.VirtQueue"
+
 #include <xdc/std.h>
 #include <xdc/runtime/System.h>
+#include <xdc/runtime/Assert.h>
 #include <xdc/runtime/Error.h>
 #include <xdc/runtime/Memory.h>
+#include <xdc/runtime/Registry.h>
 #include <xdc/runtime/Log.h>
 #include <xdc/runtime/Diags.h>
 
 #include <ti/sysbios/hal/Hwi.h>
 #include <ti/sysbios/knl/Clock.h>
-#include <ti/sysbios/gates/GateAll.h>
-#include <ti/sysbios/BIOS.h>
+#include <ti/sysbios/gates/GateHwi.h>
 #include <ti/sysbios/hal/Cache.h>
 
 #include <ti/ipc/MultiProc.h>
@@ -74,6 +79,8 @@
 #endif
 #include <string.h>
 
+#include <ti/ipc/remoteproc/Resource.h>
+#include <ti/ipc/remoteproc/rsc_types.h>
 #include <ti/ipc/rpmsg/_VirtQueue.h>
 
 #include <ti/sdo/ipc/notifyDrivers/IInterrupt.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
+#define NUM_QUEUES              2
 
 /* Predefined device addresses */
 #ifdef DSP
 #define IPC_MEM_VRING0          0xA0000000
 #define IPC_MEM_VRING1          0xA0004000
-#define IPC_MEM_VRING2          0xA0008000
-#define IPC_MEM_VRING3          0xA000c000
 #else
 #define IPC_MEM_VRING0          0x60000000
 #define IPC_MEM_VRING1          0x60004000
-#define IPC_MEM_VRING2          0x60008000
-#define IPC_MEM_VRING3          0x6000c000
 #endif
 
 /*
- * Sizes of the virtqueues (expressed in number of buffers supported,
+ * Size of the virtqueues (expressed in number of buffers supported,
  * and must be power of two)
  */
-#define VQ0_SIZE                256
-#define VQ1_SIZE                256
-#define VQ2_SIZE                256
-#define VQ3_SIZE                256
+#define VQ_SIZE                 256
 
 /*
  * enum - Predefined Mailbox Messages
@@ -151,7 +162,7 @@ enum {
 };
 
 #define DIV_ROUND_UP(n,d)   (((n) + (d) - 1) / (d))
-#define RP_MSG_NUM_BUFS     (VQ0_SIZE) /* must be power of two */
+#define RP_MSG_NUM_BUFS     (VQ_SIZE) /* must be power of two */
 #define RP_MSG_BUF_SIZE     (512)
 #define RP_MSG_BUFS_SPACE   (RP_MSG_NUM_BUFS * RP_MSG_BUF_SIZE * 2)
 
@@ -170,13 +181,6 @@ enum {
 /* The total IPC space needed to communicate with a remote processor */
 #define RPMSG_IPC_MEM   (RP_MSG_BUFS_SPACE + 2 * RP_MSG_RING_SIZE)
 
-#define ID_SYSM3_TO_A9      ID_SELF_TO_A9
-#define ID_A9_TO_SYSM3      ID_A9_TO_SELF
-#define ID_DSP_TO_A9        ID_SELF_TO_A9
-#define ID_A9_TO_DSP        ID_A9_TO_SELF
-#define ID_APPM3_TO_A9      2
-#define ID_A9_TO_APPM3      3
-
 typedef struct VirtQueue_Object {
     /* Id for this VirtQueue_Object */
     UInt16                  id;
@@ -200,25 +204,41 @@ typedef struct VirtQueue_Object {
     UInt16                  procId;
 
     /* Gate to protect from multiple threads */
-    GateAll_Handle       gateH;
+    GateHwi_Handle       gateH;
 } VirtQueue_Object;
 
+/* module diags mask */
+Registry_Desc Registry_CURDESC;
+
 static struct VirtQueue_Object *queueRegistry[NUM_QUEUES] = {NULL};
 
 static UInt16 hostProcId;
-#ifndef SMP
-static UInt16 dsp1ProcId;
-static UInt16 sysm3ProcId;
-static UInt16 appm3ProcId;
-#endif
 
 #define DSPEVENTID              5
 IInterrupt_IntInfo intInfo;
 
-#if defined(M3_ONLY) && !defined(SMP)
-extern Void OffloadM3_init();
-extern Int OffloadM3_processSysM3Tasks(UArg msg);
-#endif
+/*!
+ * ======== _VirtQueue_init ========
+ *
+ * This function adds the VirtQueue "module" to the Registry so that
+ * DIAGS will work with this non-XDC module.
+ * Since VirtQueue_init is not called by XDC-VirtQueue module clients, this
+ * function is called in the first VirtQueue fxn called: VirtQueue_create.
+ */
+static Void _VirtQueue_init()
+{
+    static int initialized = 0;
+
+    if (!initialized) {
+        Registry_Result result;
+
+        /* register with xdc.runtime to get a diags mask */
+        result = Registry_addModule(&Registry_CURDESC, MODULE_NAME);
+        Assert_isTrue(result == Registry_SUCCESS, (Assert_Id)NULL);
+
+        initialized = 1;
+    }
+}
 
 static inline Void * mapPAtoVA(UInt pa)
 {
@@ -256,9 +276,9 @@ Int VirtQueue_addUsedBuf(VirtQueue_Handle vq, Int16 head, Int len)
     struct vring_used_elem *used;
     IArg key;
 
-    key = GateAll_enter(vq->gateH);
+    key = GateHwi_enter(vq->gateH);
     if ((head > vq->vring.num) || (head < 0)) {
-        GateAll_leave(vq->gateH, key);
+        GateHwi_leave(vq->gateH, key);
         Error_raise(NULL, Error_E_generic, 0, 0);
     }
 
@@ -271,7 +291,7 @@ Int VirtQueue_addUsedBuf(VirtQueue_Handle vq, Int16 head, Int len)
     used->len = len;
 
     vq->vring.used->idx++;
-    GateAll_leave(vq->gateH, key);
+    GateHwi_leave(vq->gateH, key);
 
     return (0);
 }
@@ -291,12 +311,12 @@ Int VirtQueue_addAvailBuf(VirtQueue_Object *vq, Void *buf)
 
     vq->num_free--;
 
-    key = GateAll_enter(vq->gateH);
+    key = GateHwi_enter(vq->gateH);
     avail =  vq->vring.avail->idx++ % vq->vring.num;
 
     vq->vring.desc[avail].addr = mapVAtoPA(buf);
     vq->vring.desc[avail].len = RP_MSG_BUF_SIZE;
-    GateAll_leave(vq->gateH, key);
+    GateHwi_leave(vq->gateH, key);
 
     return (vq->num_free);
 }
@@ -310,7 +330,7 @@ Void *VirtQueue_getUsedBuf(VirtQueue_Object *vq)
     Void *buf;
     IArg key;
 
-    key = GateAll_enter(vq->gateH);
+    key = GateHwi_enter(vq->gateH);
     /* There's nothing available? */
     if (vq->last_used_idx == vq->vring.used->idx) {
         buf = NULL;
@@ -321,7 +341,7 @@ Void *VirtQueue_getUsedBuf(VirtQueue_Object *vq)
 
         buf = mapPAtoVA(vq->vring.desc[head].addr);
     }
-    GateAll_leave(vq->gateH, key);
+    GateHwi_leave(vq->gateH, key);
 
     return (buf);
 }
@@ -334,18 +354,25 @@ Int16 VirtQueue_getAvailBuf(VirtQueue_Handle vq, Void **buf, Int *len)
     Int16 head;
     IArg key;
 
-    key = GateAll_enter(vq->gateH);
+    key = GateHwi_enter(vq->gateH);
     Log_print6(Diags_USER1, "getAvailBuf vq: 0x%x %d %d %d 0x%x 0x%x\n",
         (IArg)vq, vq->last_avail_idx, vq->vring.avail->idx, vq->vring.num,
         (IArg)&vq->vring.avail, (IArg)vq->vring.avail);
 
+    /*  Clear flag here to avoid race condition with remote processor.
+     *  This is a negative flag, clearing it means that we want to
+     *  receive an interrupt when a buffer has been added to the pool.
+     */
+    vq->vring.used->flags &= ~VRING_USED_F_NO_NOTIFY;
+
     /* 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;
         head = (-1);
     }
     else {
+        /* No need to 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.
@@ -355,7 +382,7 @@ Int16 VirtQueue_getAvailBuf(VirtQueue_Handle vq, Void **buf, Int *len)
         *buf = mapPAtoVA(vq->vring.desc[head].addr);
         *len = vq->vring.desc[head].len;
     }
-    GateAll_leave(vq->gateH, key);
+    GateHwi_leave(vq->gateH, key);
 
     return (head);
 }
@@ -365,7 +392,7 @@ Int16 VirtQueue_getAvailBuf(VirtQueue_Handle vq, Void **buf, Int *len)
  */
 Void VirtQueue_disableCallback(VirtQueue_Object *vq)
 {
-    //TODO
+    /* TODO */
     Log_print0(Diags_USER1, "VirtQueue_disableCallback called.");
 }
 
@@ -376,7 +403,7 @@ Bool VirtQueue_enableCallback(VirtQueue_Object *vq)
 {
     Log_print0(Diags_USER1, "VirtQueue_enableCallback called.");
 
-    //TODO
+    /* TODO */
     return (FALSE);
 }
 
@@ -392,100 +419,65 @@ Void VirtQueue_isr(UArg msg)
 
     Log_print1(Diags_USER1, "VirtQueue_isr received msg = 0x%x\n", msg);
 
-#ifndef SMP
-    if (MultiProc_self() == sysm3ProcId || MultiProc_self() == dsp1ProcId) {
-#endif
-        switch(msg) {
-            case (UInt)RP_MSG_MBOX_READY:
-                return;
+    switch(msg) {
+        case (UInt)RP_MSG_MBOX_READY:
+            return;
 
-            case (UInt)RP_MBOX_ECHO_REQUEST:
-                InterruptProxy_intSend(hostProcId, NULL,
-                                       (UInt)(RP_MBOX_ECHO_REPLY));
-                return;
+        case (UInt)RP_MBOX_ECHO_REQUEST:
+            InterruptProxy_intSend(hostProcId, NULL, (UInt)(RP_MBOX_ECHO_REPLY));
+            return;
 
-            case (UInt)RP_MBOX_ABORT_REQUEST:
-                {
-                    /* Suppress Coverity Error: FORWARD_NULL: */
-                    // coverity[assign_zero]
-                    Fxn f = (Fxn)0x0;
-                    Log_print0(Diags_USER1, "Crash on demand ...\n");
-                    // coverity[var_deref_op]
-                    f();
-                }
-                return;
+        case (UInt)RP_MBOX_ABORT_REQUEST:
+            {
+                /* Suppress Coverity Error: FORWARD_NULL: */
+                /* coverity[assign_zero] */
+                Fxn f = (Fxn)0x0;
+                Log_print0(Diags_USER1, "Crash on demand ...\n");
+                /* coverity[var_deref_op] */
+                f();
+            }
+            return;
 
-            case (UInt)RP_MSG_FLUSH_CACHE:
-                Cache_wbAll();
-                return;
+        case (UInt)RP_MSG_FLUSH_CACHE:
+            Cache_wbAll();
+            return;
 
 #ifndef DSP
-            case (UInt)RP_MSG_HIBERNATION:
-                if (IpcPower_canHibernate() == FALSE) {
-                    InterruptProxy_intSend(hostProcId, NULL,
-                                           (UInt)RP_MSG_HIBERNATION_CANCEL);
-                    return;
-                }
-
-            /* Fall through */
-            case (UInt)RP_MSG_HIBERNATION_FORCE:
-#ifndef SMP
-                /* Core0 should notify Core1 */
-                if (MultiProc_self() == sysm3ProcId) {
-                    InterruptProxy_intSend(appm3ProcId, NULL,
-                                           (UInt)(RP_MSG_HIBERNATION));
-                }
-#endif
-                /* Ack request */
+        case (UInt)RP_MSG_HIBERNATION:
+            if (IpcPower_canHibernate() == FALSE) {
                 InterruptProxy_intSend(hostProcId, NULL,
-                                       (UInt)RP_MSG_HIBERNATION_ACK);
-                IpcPower_suspend();
+                        (UInt)RP_MSG_HIBERNATION_CANCEL);
                 return;
-#endif
-            default:
-#if defined(M3_ONLY) && !defined(SMP)
-                /* Check and process any Inter-M3 Offload messages */
-                if (OffloadM3_processSysM3Tasks(msg))
-                    return;
-#endif
+            }
 
-                /*
-                 *  If the message isn't one of the above, it's either part of the
-                 *  2-message synchronization sequence or it a virtqueue message
-                 */
-                break;
-        }
-#ifndef SMP
-    }
-    else if (msg & 0xFFFF0000) {
-#ifndef DSP
-        if (msg == (UInt)RP_MSG_HIBERNATION) {
+            /* Fall through */
+        case (UInt)RP_MSG_HIBERNATION_FORCE:
+            /* Ack request */
+            InterruptProxy_intSend(hostProcId, NULL,
+                    (UInt)RP_MSG_HIBERNATION_ACK);
             IpcPower_suspend();
-        }
+            return;
 #endif
-        return;
+        default:
+            /*
+             *  If the message isn't one of the above, it's either part of the
+             *  2-message synchronization sequence or it a virtqueue message
+             */
+            break;
     }
 
-    if (MultiProc_self() == sysm3ProcId && (msg == ID_A9_TO_APPM3 || msg == ID_APPM3_TO_A9)) {
-        InterruptProxy_intSend(appm3ProcId, NULL, (UInt)msg);
+    /* Don't let unknown messages to pass as a virtqueue index */
+    if (msg >= NUM_QUEUES) {
+        /* Adding print here deliberately, we should never see this */
+        System_printf("VirtQueue_isr: Invalid mailbox message 0x%x "
+                "received\n", msg);
+        return;
     }
-    else {
-#endif
-        /* Don't let unknown messages to pass as a virtqueue index */
-        if (msg >= NUM_QUEUES) {
-            /* Adding print here deliberately, we should never see this */
-            System_printf("VirtQueue_isr: Invalid mailbox message 0x%x "
-                          "received\n", msg);
-            return;
-        }
 
-        vq = queueRegistry[msg];
-        if (vq) {
-            vq->callback(vq);
-        }
-#ifndef SMP
+    vq = queueRegistry[msg];
+    if (vq) {
+        vq->callback(vq);
     }
-#endif
 }
 
 
@@ -498,13 +490,16 @@ VirtQueue_Handle VirtQueue_create(UInt16 remoteProcId, VirtQueue_Params *params,
     VirtQueue_Object *vq;
     Void *vringAddr;
 
+    /* Perform initialization we can't do in Instance_init (being non-XDC): */
+    _VirtQueue_init();
+
     vq = Memory_alloc(NULL, sizeof(VirtQueue_Object), 0, eb);
     if (NULL == vq) {
         return (NULL);
     }
 
     /* Create the thread protection gate */
-    vq->gateH = GateAll_create(NULL, eb);
+    vq->gateH = GateHwi_create(NULL, eb);
     if (Error_check(eb)) {
         Log_error0("VirtQueue_create: could not create gate object");
         Memory_free(NULL, vq, sizeof(VirtQueue_Object));
@@ -516,14 +511,6 @@ VirtQueue_Handle VirtQueue_create(UInt16 remoteProcId, VirtQueue_Params *params,
     vq->procId = remoteProcId;
     vq->last_avail_idx = 0;
 
-#ifndef SMP
-    if (MultiProc_self() == appm3ProcId) {
-        /* vqindices that belong to AppM3 should be big so they don't
-         * collide with SysM3's virtqueues */
-         vq->id += 2;
-    }
-#endif
-
     switch (vq->id) {
         /* IPC transport vrings */
         case ID_SELF_TO_A9:
@@ -534,18 +521,8 @@ VirtQueue_Handle VirtQueue_create(UInt16 remoteProcId, VirtQueue_Params *params,
             /* A9 -> IPU/DSP */
             vringAddr = (struct vring *) IPC_MEM_VRING1;
             break;
-#ifndef SMP
-        case ID_APPM3_TO_A9:
-            /* APPM3 -> A9 */
-            vringAddr = (struct vring *) IPC_MEM_VRING2;
-            break;
-        case ID_A9_TO_APPM3:
-            /* A9 -> APPM3 */
-            vringAddr = (struct vring *) IPC_MEM_VRING3;
-            break;
-#endif
         default:
-            GateAll_delete(&vq->gateH);
+            GateHwi_delete(&vq->gateH);
             Memory_free(NULL, vq, sizeof(VirtQueue_Object));
             return (NULL);
     }
@@ -555,7 +532,7 @@ VirtQueue_Handle VirtQueue_create(UInt16 remoteProcId, VirtQueue_Params *params,
             RP_MSG_RING_SIZE);
 
     /* See coverity related comment in vring_init() */
-    // coverity[overrun-call]
+    /* coverity[overrun-call] */
     vring_init(&(vq->vring), RP_MSG_NUM_BUFS, vringAddr, RP_MSG_VRING_ALIGN);
 
     /*
@@ -563,7 +540,7 @@ VirtQueue_Handle VirtQueue_create(UInt16 remoteProcId, VirtQueue_Params *params,
      *  available
      */
     if (vq->procId == hostProcId) {
-        vq->vring.used->flags |= VRING_USED_F_NO_NOTIFY;
+        vq->vring.used->flags &= ~VRING_USED_F_NO_NOTIFY;
     }
 
     queueRegistry[vq->id] = vq;
@@ -577,11 +554,6 @@ VirtQueue_Handle VirtQueue_create(UInt16 remoteProcId, VirtQueue_Params *params,
 Void VirtQueue_startup()
 {
     hostProcId      = MultiProc_getId("HOST");
-#ifndef SMP
-    dsp1ProcId       = MultiProc_getId("DSP1");
-    sysm3ProcId     = MultiProc_getId("CORE0");
-    appm3ProcId     = MultiProc_getId("CORE1");
-#endif
 
 #ifdef DSP
     intInfo.intVectorId = DSPEVENTID;
@@ -590,7 +562,22 @@ Void VirtQueue_startup()
     IpcPower_init();
 #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(hostProcId, &intInfo, (Fxn)VirtQueue_isr, NULL);
+    Log_print0(Diags_USER1, "Passed VirtQueue_startup\n");
 }
 
 /*!