gpuserv: Add new vchiq service for executing vpu and qpu jobs
authorpopcornmix <popcornmix@gmail.com>
Mon, 13 Feb 2017 18:26:35 +0000 (18:26 +0000)
committerpopcornmix <popcornmix@gmail.com>
Mon, 13 Feb 2017 18:26:48 +0000 (18:26 +0000)
interface/vmcs_host/CMakeLists.txt
interface/vmcs_host/vc_vchi_gpuserv.c [new file with mode: 0755]
interface/vmcs_host/vc_vchi_gpuserv.h [new file with mode: 0755]

index 0b3adc902a64b85693beec6c6a2039ba6b94ba43..fde18dafc3ca3dea028dc272b54731b122c1a622 100755 (executable)
@@ -11,7 +11,7 @@ include_directories(${VMCS_TARGET}/vcfiled)
 
 add_library(vchostif
             ${VMCS_TARGET}/vcfilesys.c ${VMCS_TARGET}/vcmisc.c
-            vc_vchi_gencmd.c vc_vchi_filesys.c
+            vc_vchi_gencmd.c vc_vchi_filesys.c vc_vchi_gpuserv.c
             vc_vchi_tvservice.c vc_vchi_cecservice.c
             vc_vchi_dispmanx.c vc_service_common.c)
 #            ${VMCS_TARGET}/vmcs_main.c
diff --git a/interface/vmcs_host/vc_vchi_gpuserv.c b/interface/vmcs_host/vc_vchi_gpuserv.c
new file mode 100755 (executable)
index 0000000..7cd4358
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+Copyright (c) 2016, Raspberry Pi (Trading) Ltd
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the copyright holder nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include "vchost.h"
+
+#include "interface/vcos/vcos.h"
+#include "interface/vcos/vcos_logging.h"
+#include "vcinclude/common.h"
+#include "vc_vchi_gpuserv.h"
+#include "vchiq.h"
+#include "interface/vcos/vcos_stdbool.h"
+
+// VCOS logging category
+static VCOS_LOG_CAT_T vcos_log_category;
+#define VCOS_LOG_CATEGORY  (&vcos_log_category)
+
+static VCHIQ_INSTANCE_T gpuserv_client_vchiq_instance;
+static VCOS_ONCE_T gpuserv_client_once = VCOS_ONCE_INIT;
+
+/******************************************************************************
+Local types and defines.
+******************************************************************************/
+#define GPUSERV_MAX_LENGTH 512
+typedef struct {
+   VCHIQ_SERVICE_HANDLE_T service;
+   VCOS_MUTEX_T          lock;
+   int                   initialised;
+   VCOS_EVENT_T          message_available_event;
+   int refcount;
+} GPUSERV_SERVICE_T;
+
+static GPUSERV_SERVICE_T gpuserv_client;
+
+
+/******************************************************************************
+Static function.
+******************************************************************************/
+static VCHIQ_STATUS_T gpuserv_callback( VCHIQ_REASON_T reason,
+                                        VCHIQ_HEADER_T *header,
+                                        VCHIQ_SERVICE_HANDLE_T vchiq_handle,
+                                        void *bulk_userdata );
+
+static void init_once(void)
+{
+   vcos_mutex_create(&gpuserv_client.lock, VCOS_FUNCTION);
+}
+
+/******************************************************************************
+NAME
+
+   vc_gpuserv_init
+
+SYNOPSIS
+   int32_t vc_gpuserv_init( void )
+
+FUNCTION
+   Initialise the gpu service for use. A negative return value
+   indicates failure (which may mean it has not been started on VideoCore).
+
+RETURNS
+   zero on success
+******************************************************************************/
+
+int32_t vc_gpuserv_init( void )
+{
+   VCHIQ_SERVICE_PARAMS_T vchiq_params;
+   VCOS_STATUS_T status = VCOS_ENXIO;
+   VCHIQ_STATUS_T vchiq_status;
+
+   vcos_once(&gpuserv_client_once, init_once);
+
+   vcos_mutex_lock(&gpuserv_client.lock);
+
+   if (gpuserv_client.refcount++ > 0)
+   {
+      /* Already initialised so nothing to do */
+      vcos_mutex_unlock(&gpuserv_client.lock);
+      return VCOS_SUCCESS;
+   }
+
+   vcos_log_set_level(VCOS_LOG_CATEGORY, VCOS_LOG_TRACE);
+   vcos_log_register("gpuserv", VCOS_LOG_CATEGORY);
+
+   vcos_log_trace("%s: starting initialisation", VCOS_FUNCTION);
+
+   /* Initialise a VCHIQ instance */
+   vchiq_status = vchiq_initialise(&gpuserv_client_vchiq_instance);
+   if (vchiq_status != VCHIQ_SUCCESS)
+   {
+      vcos_log_error("%s: failed to initialise vchiq: %d", VCOS_FUNCTION, vchiq_status);
+      goto error;
+   }
+
+   vchiq_status = vchiq_connect(gpuserv_client_vchiq_instance);
+   if (vchiq_status != VCHIQ_SUCCESS)
+   {
+      vcos_log_error("%s: failed to connect to vchiq: %d", VCOS_FUNCTION, vchiq_status);
+      goto error;
+   }
+
+   memset(&vchiq_params, 0, sizeof(vchiq_params));
+   vchiq_params.fourcc = VCHIQ_MAKE_FOURCC('G','P','U','S');
+   vchiq_params.callback = gpuserv_callback;
+   vchiq_params.userdata = NULL;
+   vchiq_params.version = 1;
+   vchiq_params.version_min = 1;
+
+   vchiq_status = vchiq_open_service(gpuserv_client_vchiq_instance, &vchiq_params, &gpuserv_client.service);
+   if (vchiq_status != VCHIQ_SUCCESS)
+   {
+      vcos_log_error("%s: could not open vchiq service: %d", VCOS_FUNCTION, vchiq_status);
+      goto error;
+   }
+   vcos_mutex_unlock(&gpuserv_client.lock);
+   return 0;
+error:
+   vcos_mutex_unlock(&gpuserv_client.lock);
+   return -1;
+}
+
+/******************************************************************************
+NAME
+   gpuserv_callback
+
+SYNOPSIS
+   void gpuserv_callback( VCHIQ_REASON_T reason,
+                          VCHIQ_HEADER_T *header,
+                          VCHIQ_SERVICE_HANDLE_T service,
+                          void *bulk_userdata )
+FUNCTION
+   VCHIQ callback
+
+RETURNS
+   zero on success
+******************************************************************************/
+static VCHIQ_STATUS_T gpuserv_callback( VCHIQ_REASON_T reason,
+                                        VCHIQ_HEADER_T *header,
+                                        VCHIQ_SERVICE_HANDLE_T service,
+                                        void *bulk_userdata )
+{
+   GPUSERV_SERVICE_T *instance = (GPUSERV_SERVICE_T *)bulk_userdata;
+
+   (void)header;
+
+   // reason is one of VCHIQ_MESSAGE_AVAILABLE, VCHIQ_BULK_TRANSMIT_DONE, VCHIQ_BULK_RECEIVE_DONE
+   switch (reason)
+   {
+      case VCHIQ_MESSAGE_AVAILABLE:
+      {
+         struct gpu_callback_s *c = (struct gpu_callback_s *)header->data;
+         if (c->func)
+            c->func(c->cookie);
+         vchiq_release_message(service, header);
+         break;
+      }
+      default:
+        ;
+   }
+   return 0; // Releases any command message (VCHIQ_MESSAGE_AVAILABLE), ignored otherwise
+}
+
+/******************************************************************************
+NAME
+   vc_gpuserv_execute_code
+
+SYNOPSIS
+   int32_t vc_gpuserv_execute_code(int num_jobs, struct gpu_job_s jobs[])
+
+FUNCTION
+   Submit a list of VPU/QPU jobs to be exeected by GPU
+
+RETURNS
+   zero on success
+******************************************************************************/
+#define MAX_JOBS 8
+int32_t vc_gpuserv_execute_code(int num_jobs, struct gpu_job_s jobs[])
+{
+   VCHIQ_ELEMENT_T elements[MAX_JOBS];
+   int i;
+
+   if (vc_gpuserv_init() != 0)
+   {
+      vcos_log_error("%s: vchiq service not initialised", VCOS_FUNCTION);
+      return -1;
+   }
+   if (num_jobs > MAX_JOBS)
+      return -1;
+
+   for (i=0; i<num_jobs; i++)
+   {
+      elements[i].data = jobs + i;
+      elements[i].size = sizeof *jobs;
+   }
+   if (vchiq_queue_message(gpuserv_client.service, elements, num_jobs) != VCHIQ_SUCCESS)
+   {
+      goto error_exit;
+   }
+   return 0;
+   error_exit:
+   return -1; 
+}
diff --git a/interface/vmcs_host/vc_vchi_gpuserv.h b/interface/vmcs_host/vc_vchi_gpuserv.h
new file mode 100755 (executable)
index 0000000..b3c9bf5
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+Copyright (c) 2016, Raspberry Pi (Trading) Ltd
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the copyright holder nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef VC_VCHI_GPUSERV_H
+#define VC_VCHI_GPUSERV_H
+#include "interface/vchiq_arm/vchiq.h"
+
+// these go in command word of gpu_job_s
+// EXECUTE_VPU and EXECUTE_QPU are valid from host
+enum { EXECUTE_NONE, EXECUTE_VPU, EXECUTE_QPU, EXECUTE_SYNC };
+
+struct vpu_job_s {
+   // these are function address and parameters for vpu job
+   uint32_t q[7];
+   uint32_t dummy[21];
+};
+
+struct qpu_job_s {
+   // parameters for qpu job
+   uint32_t jobs;
+   uint32_t noflush;
+   uint32_t timeout;
+   uint32_t dummy;
+   uint32_t control[12][2];
+};
+
+struct sync_job_s {
+   // parameters for syncjob
+   // bit 0 set means wait for preceding vpu jobs to complete
+   // bit 1 set means wait for preceding qpu jobs to complete
+   uint32_t mask;
+   uint32_t dummy[27];
+};
+
+struct gpu_callback_s {
+  // callback to call when complete (can be NULL)
+  void (*func)();
+  void *cookie;
+};
+
+struct gpu_internal_s {
+   void *message;
+   int refcount;
+};
+
+struct gpu_job_s {
+  // from enum above
+  uint32_t command;
+  // qpu or vpu jobs
+  union {
+    struct vpu_job_s v;
+    struct qpu_job_s q;
+    struct sync_job_s s;
+  } u;
+  // callback function to call when complete
+  struct gpu_callback_s callback;
+  // for internal use - leave as zero
+  struct gpu_internal_s internal;
+};
+
+/* Initialise gpu service. Returns its interface number. This initialises
+   the host side of the interface, it does not send anything to VideoCore. */
+
+VCHPRE_ int32_t VCHPOST_ vc_gpuserv_init(void);
+
+VCHPRE_ int32_t VCHPOST_ vc_gpuserv_execute_code(int num_jobs, struct gpu_job_s jobs[]);
+
+#endif