Module Name:    src
Committed By:   skrll
Date:           Thu Jan 12 05:41:25 UTC 2017

Modified Files:
        src/sys/external/bsd/vchiq/dist/interface/vchi: vchi.h vchi_common.h
        src/sys/external/bsd/vchiq/dist/interface/vchiq_arm: vchiq.h
            vchiq_2835_arm.c vchiq_arm.c vchiq_arm.h vchiq_cfg.h
            vchiq_connected.h vchiq_core.c vchiq_core.h vchiq_genversion
            vchiq_if.h vchiq_ioctl.h vchiq_shim.c vchiq_util.c vchiq_util.h
Added Files:
        src/sys/external/bsd/vchiq/dist/interface/vchiq_arm: vchiq_debugfs.h
Removed Files:
        src/sys/external/bsd/vchiq/dist/interface/vchiq_arm: vchiq_proc.c

Log Message:
Sync with latest github/raspberrypi/linux sources

XXX should provide a vchiq2netbsd and cvs import


To generate a diff of this commit:
cvs rdiff -u -r1.1 -r1.2 \
    src/sys/external/bsd/vchiq/dist/interface/vchi/vchi.h \
    src/sys/external/bsd/vchiq/dist/interface/vchi/vchi_common.h
cvs rdiff -u -r1.1 -r1.2 \
    src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq.h \
    src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_arm.h \
    src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_cfg.h \
    src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_connected.h \
    src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_genversion
cvs rdiff -u -r1.17 -r1.18 \
    src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_2835_arm.c \
    src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_arm.c
cvs rdiff -u -r1.10 -r1.11 \
    src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_core.c
cvs rdiff -u -r1.3 -r1.4 \
    src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_core.h
cvs rdiff -u -r0 -r1.1 \
    src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_debugfs.h
cvs rdiff -u -r1.2 -r1.3 \
    src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_if.h \
    src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_ioctl.h \
    src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_util.c \
    src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_util.h
cvs rdiff -u -r1.2 -r0 \
    src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_proc.c
cvs rdiff -u -r1.5 -r1.6 \
    src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_shim.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/external/bsd/vchiq/dist/interface/vchi/vchi.h
diff -u src/sys/external/bsd/vchiq/dist/interface/vchi/vchi.h:1.1 src/sys/external/bsd/vchiq/dist/interface/vchi/vchi.h:1.2
--- src/sys/external/bsd/vchiq/dist/interface/vchi/vchi.h:1.1	Fri Mar  8 12:32:30 2013
+++ src/sys/external/bsd/vchiq/dist/interface/vchi/vchi.h	Thu Jan 12 05:41:25 2017
@@ -220,7 +220,12 @@ extern int32_t vchi_service_use( const V
 // Routine to decrement ref count on a named service
 extern int32_t vchi_service_release( const VCHI_SERVICE_HANDLE_T handle );
 
-// Routine to send a message accross a service
+// Routine to set a control option for a named service
+extern int32_t vchi_service_set_option( const VCHI_SERVICE_HANDLE_T handle,
+					VCHI_SERVICE_OPTION_T option,
+					int value);
+
+// Routine to send a message across a service
 extern int32_t vchi_msg_queue( VCHI_SERVICE_HANDLE_T handle,
                                const void *data,
                                uint32_t data_size,
Index: src/sys/external/bsd/vchiq/dist/interface/vchi/vchi_common.h
diff -u src/sys/external/bsd/vchiq/dist/interface/vchi/vchi_common.h:1.1 src/sys/external/bsd/vchiq/dist/interface/vchi/vchi_common.h:1.2
--- src/sys/external/bsd/vchiq/dist/interface/vchi/vchi_common.h:1.1	Fri Mar  8 12:32:30 2013
+++ src/sys/external/bsd/vchiq/dist/interface/vchi/vchi_common.h	Thu Jan 12 05:41:25 2017
@@ -110,7 +110,19 @@ typedef enum
    VCHI_CALLBACK_REASON_MAX
 } VCHI_CALLBACK_REASON_T;
 
-//Calback used by all services / bulk transfers
+// service control options
+typedef enum
+{
+   VCHI_SERVICE_OPTION_MIN,
+
+   VCHI_SERVICE_OPTION_TRACE,
+   VCHI_SERVICE_OPTION_SYNCHRONOUS,
+
+   VCHI_SERVICE_OPTION_MAX
+} VCHI_SERVICE_OPTION_T;
+
+
+//Callback used by all services / bulk transfers
 typedef void (*VCHI_CALLBACK_T)( void *callback_param, //my service local param
                                  VCHI_CALLBACK_REASON_T reason,
                                  void *handle ); //for transmitting msg's only

Index: src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq.h
diff -u src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq.h:1.1 src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq.h:1.2
--- src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq.h:1.1	Fri Mar  8 12:32:30 2013
+++ src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq.h	Thu Jan 12 05:41:25 2017
@@ -38,4 +38,3 @@
 #include "vchiq_util.h"
 
 #endif
-
Index: src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_arm.h
diff -u src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_arm.h:1.1 src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_arm.h:1.2
--- src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_arm.h:1.1	Fri Mar  8 12:32:31 2013
+++ src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_arm.h	Thu Jan 12 05:41:25 2017
@@ -1,4 +1,5 @@
 /**
+ * Copyright (c) 2014 Raspberry Pi (Trading) Ltd. All rights reserved.
  * Copyright (c) 2010-2012 Broadcom. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -35,6 +36,7 @@
 #define VCHIQ_ARM_H
 
 #include "vchiq_core.h"
+#include "vchiq_debugfs.h"
 
 
 enum vc_suspend_status {
@@ -152,6 +154,14 @@ vchiq_check_resume(VCHIQ_STATE_T *state)
 
 extern void
 vchiq_check_suspend(VCHIQ_STATE_T *state);
+ VCHIQ_STATUS_T
+vchiq_use_service(VCHIQ_SERVICE_HANDLE_T handle);
+
+extern VCHIQ_STATUS_T
+vchiq_release_service(VCHIQ_SERVICE_HANDLE_T handle);
+
+extern VCHIQ_STATUS_T
+vchiq_check_service(VCHIQ_SERVICE_T *service);
 
 extern VCHIQ_STATUS_T
 vchiq_platform_suspend(VCHIQ_STATE_T *state);
@@ -180,21 +190,31 @@ vchiq_use_internal(VCHIQ_STATE_T *state,
 extern VCHIQ_STATUS_T
 vchiq_release_internal(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service);
 
-void
+// extern VCHIQ_DEBUGFS_NODE_T *
+// vchiq_instance_get_debugfs_node(VCHIQ_INSTANCE_T instance);
+
+extern int
+vchiq_instance_get_use_count(VCHIQ_INSTANCE_T instance);
+
+extern int
+vchiq_instance_get_pid(VCHIQ_INSTANCE_T instance);
+
+extern int
+vchiq_instance_get_trace(VCHIQ_INSTANCE_T instance);
+
+extern void
+vchiq_instance_set_trace(VCHIQ_INSTANCE_T instance, int trace);
+
+extern void
 set_suspend_state(VCHIQ_ARM_STATE_T *arm_state,
 	enum vc_suspend_status new_state);
 
-void
+extern void
 set_resume_state(VCHIQ_ARM_STATE_T *arm_state,
 	enum vc_resume_status new_state);
 
-void
+extern void
 start_suspend_timer(VCHIQ_ARM_STATE_T *arm_state);
 
-extern int vchiq_proc_init(void);
-extern void vchiq_proc_deinit(void);
-extern struct proc_dir_entry *vchiq_proc_top(void);
-extern struct proc_dir_entry *vchiq_clients_top(void);
-
 
 #endif /* VCHIQ_ARM_H */
Index: src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_cfg.h
diff -u src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_cfg.h:1.1 src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_cfg.h:1.2
--- src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_cfg.h:1.1	Fri Mar  8 12:32:31 2013
+++ src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_cfg.h	Thu Jan 12 05:41:25 2017
@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2010-2012 Broadcom. All rights reserved.
+ * Copyright (c) 2010-2014 Broadcom. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -36,11 +36,20 @@
 
 #define VCHIQ_MAGIC              VCHIQ_MAKE_FOURCC('V', 'C', 'H', 'I')
 /* The version of VCHIQ - change with any non-trivial change */
-#define VCHIQ_VERSION            6
+#define VCHIQ_VERSION            8
 /* The minimum compatible version - update to match VCHIQ_VERSION with any
 ** incompatible change */
 #define VCHIQ_VERSION_MIN        3
 
+/* The version that introduced the VCHIQ_IOC_LIB_VERSION ioctl */
+#define VCHIQ_VERSION_LIB_VERSION 7
+
+/* The version that introduced the VCHIQ_IOC_CLOSE_DELIVERED ioctl */
+#define VCHIQ_VERSION_CLOSE_DELIVERED 7
+
+/* The version that made it safe to use SYNCHRONOUS mode */
+#define VCHIQ_VERSION_SYNCHRONOUS_MODE 8
+
 #define VCHIQ_MAX_STATES         1
 #define VCHIQ_MAX_SERVICES       4096
 #define VCHIQ_MAX_SLOTS          128
Index: src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_connected.h
diff -u src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_connected.h:1.1 src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_connected.h:1.2
--- src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_connected.h:1.1	Fri Mar  8 12:32:31 2013
+++ src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_connected.h	Thu Jan 12 05:41:25 2017
@@ -48,4 +48,3 @@ void vchiq_add_connected_callback(VCHIQ_
 void vchiq_call_connected_callbacks(void);
 
 #endif /* VCHIQ_CONNECTED_H */
-
Index: src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_genversion
diff -u src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_genversion:1.1 src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_genversion:1.2
--- src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_genversion:1.1	Fri Mar  8 12:32:31 2013
+++ src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_genversion	Thu Jan 12 05:41:25 2017
@@ -41,11 +41,11 @@ if ( -d "$root/.git" ) {
 			$tainted =~ s/[ \r\n]*$//;     # chomp may not be enough (cygwin).
 			$tainted =~ s/^[ \r\n]*//;     # chomp may not be enough (cygwin).
 			if (length $tainted) {
-   			$version = join ' ', $version, "(tainted)";
-   		}
-   		else {
-   			$version = join ' ', $version, "(clean)";
-         }   		
+			$version = join ' ', $version, "(tainted)";
+		}
+		else {
+			$version = join ' ', $version, "(clean)";
+         }
 		}
 	}
 }
@@ -85,5 +85,3 @@ const char *vchiq_get_build_time( void )
    return vchiq_build_time;
 }
 EOF
-
-

Index: src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_2835_arm.c
diff -u src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_2835_arm.c:1.17 src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_2835_arm.c:1.18
--- src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_2835_arm.c:1.17	Thu May  1 03:07:50 2014
+++ src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_2835_arm.c	Thu Jan 12 05:41:25 2017
@@ -63,16 +63,17 @@ typedef struct vchiq_2835_state_struct {
    VCHIQ_ARM_STATE_T arm_state;
 } VCHIQ_2835_ARM_STATE_T;
 
-static char *g_slot_mem;
-static int g_slot_mem_size;
-paddr_t g_slot_phys, g_slot_phys_cpu;
 /* BSD DMA */
 static bus_dmamap_t dma_map;
-static FRAGMENTS_T *g_fragments_base;
-static FRAGMENTS_T *g_free_fragments;
+
+static unsigned int g_cache_line_size = CACHE_LINE_SIZE;
+static unsigned int g_fragments_size;
+static char *g_fragments_base;
+static char *g_free_fragments;
+
 struct semaphore g_free_fragments_sema;
+static struct semaphore g_free_fragments_mutex;
 
-static DEFINE_SEMAPHORE(g_free_fragments_mutex);
 
 int __init
 vchiq_platform_init(VCHIQ_STATE_T *state)
@@ -80,19 +81,25 @@ vchiq_platform_init(VCHIQ_STATE_T *state
 	VCHIQ_SLOT_ZERO_T *vchiq_slot_zero;
 	bus_dma_segment_t dma_segs[1];
 	int dma_nsegs;
-	int frag_mem_size;
+	void *slot_mem;
+	bus_addr_t slot_phys;
+	int slot_mem_size, frag_mem_size;
 	int err;
 	int i;
 
 	_sema_init(&g_free_fragments_mutex, 1);
 
+	g_cache_line_size = 32;
+
+	g_fragments_size = 2 * g_cache_line_size;
+
 	/* Allocate space for the channels in coherent memory */
-	g_slot_mem_size = PAGE_ALIGN(TOTAL_SLOTS * VCHIQ_SLOT_SIZE);
-	frag_mem_size = PAGE_ALIGN(sizeof(FRAGMENTS_T) * MAX_FRAGMENTS);
+	slot_mem_size = PAGE_ALIGN(TOTAL_SLOTS * VCHIQ_SLOT_SIZE);
+	frag_mem_size = PAGE_ALIGN(g_fragments_size * MAX_FRAGMENTS);
 
 	dma_nsegs = __arraycount(dma_segs);
 	err = bus_dmamem_alloc(&bcm2835_bus_dma_tag,
-	    g_slot_mem_size + frag_mem_size, PAGE_SIZE, 0,
+	    slot_mem_size + frag_mem_size, PAGE_SIZE, 0,
 	    dma_segs, dma_nsegs, &dma_nsegs, BUS_DMA_WAITOK);
 	if (err) {
 		vchiq_log_error(vchiq_core_log_level, "Unable to allocate channel memory");
@@ -101,8 +108,8 @@ vchiq_platform_init(VCHIQ_STATE_T *state
 	}
 
 	err = bus_dmamem_map(&bcm2835_bus_dma_tag,
-	    dma_segs, dma_nsegs, g_slot_mem_size + frag_mem_size,
-	    (void **)&g_slot_mem, BUS_DMA_COHERENT | BUS_DMA_WAITOK);
+	    dma_segs, dma_nsegs, slot_mem_size + frag_mem_size,
+	    (void **)&slot_mem, BUS_DMA_COHERENT | BUS_DMA_WAITOK);
 	if (err) {
 		vchiq_log_error(vchiq_core_log_level, "Unable to map channel memory");
 		err = -ENOMEM;
@@ -110,8 +117,8 @@ vchiq_platform_init(VCHIQ_STATE_T *state
 	}
 
 	err = bus_dmamap_create(&bcm2835_bus_dma_tag,
-	    g_slot_mem_size + frag_mem_size, 1,	/* maxsize, nsegments */
-	    g_slot_mem_size + frag_mem_size, 0, /* maxsegsize, boundary */
+	    slot_mem_size + frag_mem_size, 1,	/* maxsize, nsegments */
+	    slot_mem_size + frag_mem_size, 0,	/* maxsegsize, boundary */
 	    BUS_DMA_WAITOK,
 	    &dma_map);
 	if (err) {
@@ -120,40 +127,41 @@ vchiq_platform_init(VCHIQ_STATE_T *state
 		goto failed_alloc;
 	}
 
-	err = bus_dmamap_load(&bcm2835_bus_dma_tag, dma_map, g_slot_mem,
-	    g_slot_mem_size + frag_mem_size, NULL, BUS_DMA_WAITOK);
+	err = bus_dmamap_load(&bcm2835_bus_dma_tag, dma_map, slot_mem,
+	    slot_mem_size + frag_mem_size, NULL, BUS_DMA_WAITOK);
 	if (err) {
 		vchiq_log_error(vchiq_core_log_level, "cannot load DMA map (%d)", err);
 		err = -ENOMEM;
 		goto failed_load;
 	}
-	g_slot_phys = dma_map->dm_segs[0].ds_addr;
+	slot_phys = dma_map->dm_segs[0].ds_addr;
 
 	vchiq_log_info(vchiq_arm_log_level,
-	    "%s: g_slot_phys = %x\n", __func__, (unsigned int)g_slot_phys);
+	    "%s: slot_phys = %lx\n", __func__, slot_phys);
 
-	WARN_ON(((int)g_slot_mem & (PAGE_SIZE - 1)) != 0);
+	WARN_ON(((int)slot_mem & (PAGE_SIZE - 1)) != 0);
 
-	vchiq_slot_zero = vchiq_init_slots(g_slot_mem, g_slot_mem_size);
+	vchiq_slot_zero = vchiq_init_slots(slot_mem, slot_mem_size);
 	if (!vchiq_slot_zero) {
 		err = -EINVAL;
 		goto failed_init_slots;
 	}
 
 	vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_OFFSET_IDX] =
-		(int)g_slot_phys + g_slot_mem_size;
+		(int)slot_phys + slot_mem_size;
 	vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX] =
 		MAX_FRAGMENTS;
 
-	g_fragments_base = (FRAGMENTS_T *)(g_slot_mem + g_slot_mem_size);
-	g_slot_mem_size += frag_mem_size;
+	g_fragments_base = (char *)slot_mem + slot_mem_size;
+	slot_mem_size += frag_mem_size;
 
 	g_free_fragments = g_fragments_base;
 	for (i = 0; i < (MAX_FRAGMENTS - 1); i++) {
-		*(FRAGMENTS_T **)&g_fragments_base[i] =
-			&g_fragments_base[i + 1];
+		*(char **)&g_fragments_base[i*g_fragments_size] =
+			&g_fragments_base[(i + 1)*g_fragments_size];
 	}
-	*(FRAGMENTS_T **)&g_fragments_base[i] = NULL;
+	*(char **)&g_fragments_base[i * g_fragments_size] = NULL;
+
 	_sema_init(&g_free_fragments_sema, MAX_FRAGMENTS);
 
 	if (vchiq_init_state(state, vchiq_slot_zero, 0/*slave*/) !=
@@ -162,17 +170,20 @@ vchiq_platform_init(VCHIQ_STATE_T *state
 		goto failed_vchiq_init;
 	}
 
-	bus_dmamap_sync(&bcm2835_bus_dma_tag, dma_map, 0, g_slot_mem_size,
-	    BUS_DMASYNC_PREWRITE);
-	bcm_mbox_write(BCM2835_MBOX_CHAN_VCHIQ, (unsigned int)g_slot_phys);
-	bus_dmamap_sync(&bcm2835_bus_dma_tag, dma_map, 0, g_slot_mem_size,
-	    BUS_DMASYNC_POSTWRITE);
+	/* Send the base address of the slots to VideoCore */
+	dsb(); /* Ensure all writes have completed */
+
+	bus_dmamap_sync(&bcm2835_bus_dma_tag, dma_map, 0, slot_mem_size,
+	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+	bcm_mbox_write(BCM2835_MBOX_CHAN_VCHIQ, (unsigned int)slot_phys);
+	bus_dmamap_sync(&bcm2835_bus_dma_tag, dma_map, 0, slot_mem_size,
+	    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
 
 	vchiq_log_info(vchiq_arm_log_level,
 		"vchiq_init - done (slots %x, phys %x)",
-		(unsigned int)vchiq_slot_zero, (unsigned int)g_slot_phys);
+		(unsigned int)vchiq_slot_zero, (unsigned int)slot_phys);
 
-   vchiq_call_connected_callbacks();
+	vchiq_call_connected_callbacks();
 
    return 0;
 
@@ -261,13 +272,15 @@ vchiq_prepare_bulk_data(VCHIQ_BULK_T *bu
 	int ret;
 
 	vchiq_log_info(vchiq_arm_log_level,
-	    "%s: buf %p size %08x dir %s\n", __func__, buf, size,
+	    "%s: buf %p size %08x dir %s", __func__, buf, size,
 	    dir == VCHIQ_BULK_RECEIVE ? "read" : "write");
 
 	vaddr_t va = (vaddr_t)buf;
 	const size_t maxsegs = atop(round_page(va + size) - trunc_page(va));
- 	int uvmflags = (dir == VCHIQ_BULK_RECEIVE ? VM_PROT_READ : VM_PROT_WRITE);
-	int dmaflags = (dir == VCHIQ_BULK_RECEIVE ? BUS_DMA_READ : BUS_DMA_WRITE);
+ 	const int uvmflags = (dir == VCHIQ_BULK_RECEIVE ?
+	    VM_PROT_READ : VM_PROT_WRITE);
+	const int dmaflags = (dir == VCHIQ_BULK_RECEIVE ?
+	    BUS_DMA_READ : BUS_DMA_WRITE);
 
 	WARN_ON(memhandle != VCHI_MEM_HANDLE_INVALID);
 
@@ -294,6 +307,7 @@ vchiq_prepare_bulk_data(VCHIQ_BULK_T *bu
 		goto fail2;
 
 	pagelist = bi->pagelist;
+
 	ret = bus_dmamap_create(&bcm2835_bus_dma_tag, bi->pagelist_size,
 	    nsegs, bi->pagelist_size, 0, BUS_DMA_WAITOK, &bi->pagelist_map);
 	if (ret != 0)
@@ -305,12 +319,6 @@ vchiq_prepare_bulk_data(VCHIQ_BULK_T *bu
 		goto fail4;
 
 	/*
-	 * We've now got the bus_addr_t for the pagelist we want the transfer
-	 * to use.
-	 */
-	bulk->data = (void *)bi->pagelist_map->dm_segs[0].ds_addr;
-
-	/*
 	 * Need to wire the buffer pages in.
 	 */
 	if (IS_USER_ADDRESS(buf)) {
@@ -334,6 +342,11 @@ vchiq_prepare_bulk_data(VCHIQ_BULK_T *bu
 		goto fail7;
 
 	bulk->handle = memhandle;
+	/*
+	 * We've now got the bus_addr_t for the pagelist we want the transfer
+	 * to use.
+	 */
+	bulk->data = (void *)bi->pagelist_map->dm_segs[0].ds_addr;
 
 	pagelist->type = (dir == VCHIQ_BULK_RECEIVE) ?
 	    PAGELIST_READ : PAGELIST_WRITE;
@@ -355,9 +368,9 @@ vchiq_prepare_bulk_data(VCHIQ_BULK_T *bu
 
 	/* Partial cache lines (fragments) require special measures */
 	if ((pagelist->type == PAGELIST_READ) &&
-	    ((pagelist->offset & (arm_dcache_align - 1)) ||
-	    ((pagelist->offset + pagelist->length) & (arm_dcache_align - 1)))) {
-		FRAGMENTS_T *fragments;
+	    ((pagelist->offset & (g_cache_line_size - 1)) ||
+	    ((pagelist->offset + pagelist->length) & (g_cache_line_size - 1)))) {
+		char *fragments;
 
 		if (down_interruptible(&g_free_fragments_sema) != 0) {
 			goto fail7;
@@ -366,14 +379,14 @@ vchiq_prepare_bulk_data(VCHIQ_BULK_T *bu
 		WARN_ON(g_free_fragments == NULL);
 
 		down(&g_free_fragments_mutex);
-		fragments = (FRAGMENTS_T *) g_free_fragments;
+		fragments = g_free_fragments;
 		WARN_ON(fragments == NULL);
-		g_free_fragments = *(FRAGMENTS_T **) g_free_fragments;
+		g_free_fragments = *(char **) g_free_fragments;
 		up(&g_free_fragments_mutex);
 		pagelist->type = PAGELIST_READ_WITH_FRAGMENTS +
-		    (fragments - g_fragments_base);
+		    (fragments - g_fragments_base) / g_fragments_size;
 		bus_dmamap_sync(&bcm2835_bus_dma_tag, dma_map,
-		    (char *)fragments - g_slot_mem, sizeof(*fragments),
+		    (char *)fragments - g_fragments_base, sizeof(*fragments),
 		    BUS_DMASYNC_PREREAD);
 	}
 
@@ -423,9 +436,13 @@ void
 vchiq_complete_bulk(VCHIQ_BULK_T *bulk)
 {
 	if (bulk && bulk->remote_data && bulk->actual) {
+		int actual = bulk->actual;
 		BULKINFO_T *bi = bulk->remote_data;
 		PAGELIST_T *pagelist = bi->pagelist;
 
+		vchiq_log_trace(vchiq_arm_log_level,
+			"free_pagelist - %x, %d", (unsigned int)pagelist, actual);
+
 		bus_dmamap_sync(&bcm2835_bus_dma_tag, bi->pagelist_map, 0,
 		    bi->pagelist_size, BUS_DMASYNC_POSTWRITE);
 
@@ -435,31 +452,29 @@ vchiq_complete_bulk(VCHIQ_BULK_T *bulk)
 
 		/* Deal with any partial cache lines (fragments) */
 		if (pagelist->type >= PAGELIST_READ_WITH_FRAGMENTS) {
-			FRAGMENTS_T *fragments = g_fragments_base +
-				(pagelist->type - PAGELIST_READ_WITH_FRAGMENTS);
+			char *fragments = g_fragments_base +
+			    (pagelist->type - PAGELIST_READ_WITH_FRAGMENTS) *
+			    g_fragments_size;
 			int head_bytes, tail_bytes;
-			int actual = bulk->actual;
 
 			bus_dmamap_sync(&bcm2835_bus_dma_tag, dma_map,
-			    (char *)fragments - g_slot_mem, sizeof(*fragments),
+			    (char *)fragments - g_fragments_base, g_fragments_size,
 			    BUS_DMASYNC_POSTREAD);
 
-			head_bytes = (arm_dcache_align - pagelist->offset) &
-				(arm_dcache_align - 1);
+			head_bytes = (g_cache_line_size - pagelist->offset) &
+				(g_cache_line_size - 1);
 			tail_bytes = (pagelist->offset + actual) &
-				(arm_dcache_align - 1);
+				(g_cache_line_size - 1);
 
 			if ((actual >= 0) && (head_bytes != 0)) {
 				if (head_bytes > actual)
 					head_bytes = actual;
 
 				if (IS_USER_ADDRESS(bi->buf)) {
-					copyout_proc(bi->proc,
-					    fragments->headbuf, bi->buf,
-					    head_bytes);
+					copyout_proc(bi->proc, fragments,
+					    bi->buf, head_bytes);
 				} else {
-					kcopy(fragments->headbuf, bi->buf,
-					    head_bytes);
+					kcopy(fragments, bi->buf, head_bytes);
 				}
 			}
 			if ((actual >= 0) && (head_bytes < actual) &&
@@ -469,15 +484,16 @@ vchiq_complete_bulk(VCHIQ_BULK_T *bulk)
 
 				 if (IS_USER_ADDRESS(bi->buf)) {
 					copyout_proc(bi->proc,
-					    fragments->tailbuf, t, tail_bytes);
+					    fragments + g_cache_line_size, t,
+					    tail_bytes);
 				} else {
-					kcopy(fragments->tailbuf, t,
+					kcopy(fragments + g_cache_line_size, t,
 					    tail_bytes);
 				}
 			}
 
 			down(&g_free_fragments_mutex);
-			*(FRAGMENTS_T **) fragments = g_free_fragments;
+			*(char **)fragments = g_free_fragments;
 			g_free_fragments = fragments;
 			up(&g_free_fragments_mutex);
 			up(&g_free_fragments_sema);
Index: src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_arm.c
diff -u src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_arm.c:1.17 src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_arm.c:1.18
--- src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_arm.c:1.17	Sun Jan  8 05:20:51 2017
+++ src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_arm.c	Thu Jan 12 05:41:25 2017
@@ -1,4 +1,5 @@
 /**
+ * Copyright (c) 2014 Raspberry Pi (Trading) Ltd. All rights reserved.
  * Copyright (c) 2010-2012 Broadcom. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -41,6 +42,7 @@
 #include "vchiq_core.h"
 #include "vchiq_ioctl.h"
 #include "vchiq_arm.h"
+#include "vchiq_debugfs.h"
 
 #define DEVICE_NAME "vchiq"
 
@@ -51,10 +53,10 @@
 #define VCHIQ_MINOR 0
 
 /* Some per-instance constants */
-#define MAX_COMPLETIONS 16
+#define MAX_COMPLETIONS 128
 #define MAX_SERVICES 64
 #define MAX_ELEMENTS 8
-#define MSG_QUEUE_SIZE 64
+#define MSG_QUEUE_SIZE 128
 
 #define KEEPALIVE_VER 1
 #define KEEPALIVE_VER_MIN KEEPALIVE_VER
@@ -98,23 +100,21 @@ static const char *const resume_state_na
 
 
 static void suspend_timer_callback(unsigned long context);
-#ifdef notyet
-static int vchiq_proc_add_instance(VCHIQ_INSTANCE_T instance);
-static void vchiq_proc_remove_instance(VCHIQ_INSTANCE_T instance);
-#endif
 
 
 typedef struct user_service_struct {
 	VCHIQ_SERVICE_T *service;
 	void *userdata;
 	VCHIQ_INSTANCE_T instance;
-	int is_vchi;
-	int dequeue_pending;
+	char is_vchi;
+	char dequeue_pending;
+	char close_pending;
 	int message_available_pos;
 	int msg_insert;
 	int msg_remove;
 	struct semaphore insert_event;
 	struct semaphore remove_event;
+	struct semaphore close_event;
 	VCHIQ_HEADER_T * msg_queue[MSG_QUEUE_SIZE];
 } USER_SERVICE_T;
 
@@ -137,11 +137,13 @@ struct vchiq_instance_struct {
 	int closing;
 	int pid;
 	int mark;
+	int use_close_delivered;
+	int trace;
 
 	struct list_head bulk_waiter_list;
 	struct mutex bulk_waiter_list_mutex;
 
-	struct proc_dir_entry *proc_entry;
+	VCHIQ_DEBUGFS_NODE_T debugfs_node;
 };
 
 typedef struct dump_context_struct {
@@ -170,7 +172,9 @@ static const char *const ioctl_names[] =
 	"USE_SERVICE",
 	"RELEASE_SERVICE",
 	"SET_SERVICE_OPTION",
-	"DUMP_PHYS_MEM"
+	"DUMP_PHYS_MEM",
+	"LIB_VERSION",
+	"CLOSE_DELIVERED"
 };
 
 vchiq_static_assert((sizeof(ioctl_names)/sizeof(ioctl_names[0])) ==
@@ -227,30 +231,32 @@ add_completion(VCHIQ_INSTANCE_T instance
 	void *bulk_userdata)
 {
 	VCHIQ_COMPLETION_DATA_T *completion;
+	int insert;
 	DEBUG_INITIALISE(g_state.local)
 
-	while (instance->completion_insert ==
-		(instance->completion_remove + MAX_COMPLETIONS)) {
+	insert = instance->completion_insert;
+	while ((insert - instance->completion_remove) >= MAX_COMPLETIONS) {
 		/* Out of space - wait for the client */
 		DEBUG_TRACE(SERVICE_CALLBACK_LINE);
 		vchiq_log_trace(vchiq_arm_log_level,
 			"add_completion - completion queue full");
 		DEBUG_COUNT(COMPLETION_QUEUE_FULL_COUNT);
+
 		if (down_interruptible(&instance->remove_event) != 0) {
 			vchiq_log_info(vchiq_arm_log_level,
 				"service_callback interrupted");
 			return VCHIQ_RETRY;
-		} else if (instance->closing) {
+		}
+
+		if (instance->closing) {
 			vchiq_log_info(vchiq_arm_log_level,
 				"service_callback closing");
-			return VCHIQ_ERROR;
+			return VCHIQ_SUCCESS;
 		}
 		DEBUG_TRACE(SERVICE_CALLBACK_LINE);
 	}
 
-	completion =
-		 &instance->completions[instance->completion_insert &
-		 (MAX_COMPLETIONS - 1)];
+	completion = &instance->completions[insert & (MAX_COMPLETIONS - 1)];
 
 	completion->header = header;
 	completion->reason = reason;
@@ -258,19 +264,22 @@ add_completion(VCHIQ_INSTANCE_T instance
 	completion->service_userdata = user_service->service;
 	completion->bulk_userdata = bulk_userdata;
 
-	if (reason == VCHIQ_SERVICE_CLOSED)
+	if (reason == VCHIQ_SERVICE_CLOSED) {
 		/* Take an extra reference, to be held until
 		   this CLOSED notification is delivered. */
 		lock_service(user_service->service);
+		if (instance->use_close_delivered)
+			user_service->close_pending = 1;
+	}
 
 	/* A write barrier is needed here to ensure that the entire completion
 		record is written out before the insert point. */
 	wmb();
 
 	if (reason == VCHIQ_MESSAGE_AVAILABLE)
-		user_service->message_available_pos =
-			instance->completion_insert;
-	instance->completion_insert++;
+		user_service->message_available_pos = insert;
+
+	instance->completion_insert = ++insert;
 
 	up(&instance->insert_event);
 
@@ -295,6 +304,7 @@ service_callback(VCHIQ_REASON_T reason, 
 	USER_SERVICE_T *user_service;
 	VCHIQ_SERVICE_T *service;
 	VCHIQ_INSTANCE_T instance;
+	int skip_completion = 0;
 	DEBUG_INITIALISE(g_state.local)
 
 	DEBUG_TRACE(SERVICE_CALLBACK_LINE);
@@ -308,10 +318,10 @@ service_callback(VCHIQ_REASON_T reason, 
 		return VCHIQ_SUCCESS;
 
 	vchiq_log_trace(vchiq_arm_log_level,
-		"service_callback - service %lx(%d), handle %x, reason %d, header %lx, "
+		"service_callback - service %lx(%d,%p), reason %d, header %lx, "
 		"instance %lx, bulk_userdata %lx",
 		(unsigned long)user_service,
-		service->localport, service->handle,
+		service->localport, user_service->userdata,
 		reason, (unsigned long)header,
 		(unsigned long)instance, (unsigned long)bulk_userdata);
 
@@ -361,9 +371,6 @@ service_callback(VCHIQ_REASON_T reason, 
 		user_service->msg_queue[user_service->msg_insert &
 			(MSG_QUEUE_SIZE - 1)] = header;
 		user_service->msg_insert++;
-		spin_unlock(&msg_queue_spinlock);
-
-		up(&user_service->insert_event);
 
 		/* If there is a thread waiting in DEQUEUE_MESSAGE, or if
 		** there is a MESSAGE_AVAILABLE in the completion queue then
@@ -372,13 +379,22 @@ service_callback(VCHIQ_REASON_T reason, 
 		if (((user_service->message_available_pos -
 			instance->completion_remove) >= 0) ||
 			user_service->dequeue_pending) {
-			DEBUG_TRACE(SERVICE_CALLBACK_LINE);
 			user_service->dequeue_pending = 0;
-			return VCHIQ_SUCCESS;
+			skip_completion = 1;
 		}
 
+		spin_unlock(&msg_queue_spinlock);
+
+		up(&user_service->insert_event);
+
 		header = NULL;
 	}
+
+	if (skip_completion) {
+		DEBUG_TRACE(SERVICE_CALLBACK_LINE);
+		return VCHIQ_SUCCESS;
+	}
+
 	DEBUG_TRACE(SERVICE_CALLBACK_LINE);
 
 	return add_completion(instance, reason, header, user_service,
@@ -394,7 +410,7 @@ static void
 user_service_free(void *userdata)
 {
 	USER_SERVICE_T *user_service = userdata;
-	
+
 	_sema_destroy(&user_service->insert_event);
 	_sema_destroy(&user_service->remove_event);
 
@@ -403,6 +419,28 @@ user_service_free(void *userdata)
 
 /****************************************************************************
 *
+*   close_delivered
+*
+***************************************************************************/
+static void close_delivered(USER_SERVICE_T *user_service)
+{
+	vchiq_log_info(vchiq_arm_log_level,
+		"close_delivered(handle=%x)",
+		user_service->service->handle);
+
+	if (user_service->close_pending) {
+		/* Allow the underlying service to be culled */
+		unlock_service(user_service->service);
+
+		/* Wake the user-thread blocked in close_ or remove_service */
+		up(&user_service->close_event);
+
+		user_service->close_pending = 0;
+	}
+}
+
+/****************************************************************************
+*
 *   vchiq_ioctl
 *
 ***************************************************************************/
@@ -410,15 +448,13 @@ user_service_free(void *userdata)
 static int
 vchiq_ioctl(struct file *fp, u_long cmd, void *arg)
 {
-	VCHIQ_INSTANCE_T instance;
+	VCHIQ_INSTANCE_T instance = fp->f_data;
 	VCHIQ_STATUS_T status = VCHIQ_SUCCESS;
 	VCHIQ_SERVICE_T *service = NULL;
 	int ret = 0;
 	int i, rc;
 	DEBUG_INITIALISE(g_state.local)
 
-	instance = fp->f_data;
-
 /* XXXBSD: HACK! */
 #define _IOC_NR(x) ((x) & 0xff)
 #define	_IOC_TYPE(x)	IOCGROUP(x)
@@ -480,17 +516,19 @@ vchiq_ioctl(struct file *fp, u_long cmd,
 
 	case VCHIQ_IOC_CREATE_SERVICE: {
 		VCHIQ_CREATE_SERVICE_T *pargs = arg;
+		VCHIQ_CREATE_SERVICE_T args = *pargs;
 		USER_SERVICE_T *user_service = NULL;
 		void *userdata;
 		int srvstate;
 
+		/* XXXNH kmalloc */
 		user_service = kzalloc(sizeof(USER_SERVICE_T), GFP_KERNEL);
 		if (!user_service) {
 			ret = -ENOMEM;
 			break;
 		}
 
-		if (pargs->is_open) {
+		if (args.is_open) {
 			if (!instance->connected) {
 				ret = -ENOTCONN;
 				kfree(user_service);
@@ -504,9 +542,11 @@ vchiq_ioctl(struct file *fp, u_long cmd,
 				 VCHIQ_SRVSTATE_HIDDEN;
 		}
 
-		userdata = pargs->params.userdata;
+		userdata = args.params.userdata;
 		pargs->params.callback = service_callback;
 		pargs->params.userdata = user_service;
+		args.params.callback = service_callback;
+		args.params.userdata = user_service;
 		service = vchiq_add_service_internal(
 				instance->state,
 				&pargs->params, srvstate,
@@ -516,16 +556,18 @@ vchiq_ioctl(struct file *fp, u_long cmd,
 			user_service->service = service;
 			user_service->userdata = userdata;
 			user_service->instance = instance;
-			user_service->is_vchi = pargs->is_vchi;
+			user_service->is_vchi = (args.is_vchi != 0);
 			user_service->dequeue_pending = 0;
+			user_service->close_pending = 0;
 			user_service->message_available_pos =
 				instance->completion_remove - 1;
 			user_service->msg_insert = 0;
 			user_service->msg_remove = 0;
 			_sema_init(&user_service->insert_event, 0);
 			_sema_init(&user_service->remove_event, 0);
+			_sema_init(&user_service->close_event, 0);
 
-			if (pargs->is_open) {
+			if (args.is_open) {
 				status = vchiq_open_service_internal
 					(service, instance->pid);
 				if (status != VCHIQ_SUCCESS) {
@@ -557,8 +599,24 @@ vchiq_ioctl(struct file *fp, u_long cmd,
 #endif
 
 		service = find_service_for_instance(instance, handle);
-		if (service != NULL)
-			status = vchiq_close_service(service->handle);
+		if (service != NULL) {
+			USER_SERVICE_T *user_service =
+				(USER_SERVICE_T *)service->base.userdata;
+			/* close_pending is false on first entry, and when the
+                           wait in vchiq_close_service has been interrupted. */
+			if (!user_service->close_pending) {
+				status = vchiq_close_service(service->handle);
+				if (status != VCHIQ_SUCCESS)
+					break;
+			}
+
+			/* close_pending is true once the underlying service
+			   has been closed until the client library calls the
+			   CLOSE_DELIVERED ioctl, signalling close_event. */
+			if (user_service->close_pending &&
+				down_interruptible(&user_service->close_event))
+				status = VCHIQ_RETRY;
+		}
 		else
 			ret = -EINVAL;
 	} break;
@@ -571,8 +629,24 @@ vchiq_ioctl(struct file *fp, u_long cmd,
 #endif
 
 		service = find_service_for_instance(instance, handle);
-		if (service != NULL)
-			status = vchiq_remove_service(service->handle);
+		if (service != NULL) {
+			USER_SERVICE_T *user_service =
+				(USER_SERVICE_T *)service->base.userdata;
+			/* close_pending is false on first entry, and when the
+                           wait in vchiq_close_service has been interrupted. */
+			if (!user_service->close_pending) {
+				status = vchiq_remove_service(service->handle);
+				if (status != VCHIQ_SUCCESS)
+					break;
+			}
+
+			/* close_pending is true once the underlying service
+			   has been closed until the client library calls the
+			   CLOSE_DELIVERED ioctl, signalling close_event. */
+			if (user_service->close_pending &&
+				down_interruptible(&user_service->close_event))
+				status = VCHIQ_RETRY;
+		}
 		else
 			ret = -EINVAL;
 	} break;
@@ -611,21 +685,22 @@ vchiq_ioctl(struct file *fp, u_long cmd,
 
 	case VCHIQ_IOC_QUEUE_MESSAGE: {
 		VCHIQ_QUEUE_MESSAGE_T *pargs = arg;
+		VCHIQ_QUEUE_MESSAGE_T args = *pargs;
 
 #ifdef VCHIQ_IOCTL_DEBUG
-		printf("%s: [QUEUE MESSAGE] handle = %08x\n", __func__, pargs->handle);
+		printf("%s: [QUEUE MESSAGE] handle = %08x\n", __func__, args.handle);
 #endif
 
-		service = find_service_for_instance(instance, pargs->handle);
+		service = find_service_for_instance(instance, args.handle);
 
-		if ((service != NULL) && (pargs->count <= MAX_ELEMENTS)) {
+		if ((service != NULL) && (args.count <= MAX_ELEMENTS)) {
 			/* Copy elements into kernel space */
 			VCHIQ_ELEMENT_T elements[MAX_ELEMENTS];
-			if (copy_from_user(elements, pargs->elements,
-				pargs->count * sizeof(VCHIQ_ELEMENT_T)) == 0)
+			if (copy_from_user(elements, args.elements,
+				args.count * sizeof(VCHIQ_ELEMENT_T)) == 0)
 				status = vchiq_queue_message
-					(pargs->handle,
-					elements, pargs->count);
+					(args.handle,
+					elements, args.count);
 			else
 				ret = -EFAULT;
 		} else {
@@ -636,26 +711,27 @@ vchiq_ioctl(struct file *fp, u_long cmd,
 	case VCHIQ_IOC_QUEUE_BULK_TRANSMIT:
 	case VCHIQ_IOC_QUEUE_BULK_RECEIVE: {
 		VCHIQ_QUEUE_BULK_TRANSFER_T *pargs = arg;
+		VCHIQ_QUEUE_BULK_TRANSFER_T args = *pargs;
 		struct bulk_waiter_node *waiter = NULL;
 		VCHIQ_BULK_DIR_T dir =
 			(cmd == VCHIQ_IOC_QUEUE_BULK_TRANSMIT) ?
 			VCHIQ_BULK_TRANSMIT : VCHIQ_BULK_RECEIVE;
 
-		service = find_service_for_instance(instance, pargs->handle);
+		service = find_service_for_instance(instance, args.handle);
 		if (!service) {
 			ret = -EINVAL;
 			break;
 		}
 
-		if (pargs->mode == VCHIQ_BULK_MODE_BLOCKING) {
+		if (args.mode == VCHIQ_BULK_MODE_BLOCKING) {
 			waiter = kzalloc(sizeof(struct bulk_waiter_node),
 				GFP_KERNEL);
 			if (!waiter) {
 				ret = -ENOMEM;
 				break;
 			}
-			pargs->userdata = &waiter->bulk_waiter;
-		} else if (pargs->mode == VCHIQ_BULK_MODE_WAITING) {
+			args.userdata = &waiter->bulk_waiter;
+		} else if (args.mode == VCHIQ_BULK_MODE_WAITING) {
 			struct list_head *pos;
 			lmutex_lock(&instance->bulk_waiter_list_mutex);
 			list_for_each(pos, &instance->bulk_waiter_list) {
@@ -680,13 +756,13 @@ vchiq_ioctl(struct file *fp, u_long cmd,
 			vchiq_log_info(vchiq_arm_log_level,
 				"found bulk_waiter %x for pid %d",
 				(unsigned int)waiter, current->l_proc->p_pid);
-			pargs->userdata = &waiter->bulk_waiter;
+			args.userdata = &waiter->bulk_waiter;
 		}
 		status = vchiq_bulk_transfer
-			(pargs->handle,
+			(args.handle,
 			 VCHI_MEM_HANDLE_INVALID,
-			 pargs->data, pargs->size,
-			 pargs->userdata, pargs->mode,
+			 args.data, args.size,
+			 args.userdata, args.mode,
 			 dir);
 		if (!waiter)
 			break;
@@ -718,6 +794,7 @@ vchiq_ioctl(struct file *fp, u_long cmd,
 
 	case VCHIQ_IOC_AWAIT_COMPLETION: {
 		VCHIQ_AWAIT_COMPLETION_T *pargs = arg;
+		VCHIQ_AWAIT_COMPLETION_T args = *pargs;
 		int count = 0;
 
 		DEBUG_TRACE(AWAIT_COMPLETION_LINE);
@@ -746,25 +823,29 @@ vchiq_ioctl(struct file *fp, u_long cmd,
 		}
 		DEBUG_TRACE(AWAIT_COMPLETION_LINE);
 
-		/* A read memory barrier is needed to stop prefetch of a stale
-		** completion record
-		*/
-		rmb();
-
 		if (ret == 0) {
-			int msgbufcount = pargs->msgbufcount;
+			int msgbufcount = args.msgbufcount;
+			int remove;
+
+			remove = instance->completion_remove;
 
-			for (; count < pargs->count; count++) {
+			for (count = 0; count < args.count; count++) {
 				VCHIQ_COMPLETION_DATA_T *completion;
 				VCHIQ_SERVICE_T *service1;
 				USER_SERVICE_T *user_service;
 				VCHIQ_HEADER_T *header;
-				if (instance->completion_remove ==
-					instance->completion_insert)
+
+				if (remove == instance->completion_insert)
 					break;
+
 				completion = &instance->completions[
-					instance->completion_remove &
-					(MAX_COMPLETIONS - 1)];
+					remove & (MAX_COMPLETIONS - 1)];
+
+				/* A read memory barrier is needed to prevent
+				** the prefetch of a stale completion record
+				*/
+				rmb();
+
 
 				service1 = completion->service_userdata;
 				user_service = service1->base.userdata;
@@ -779,13 +860,13 @@ vchiq_ioctl(struct file *fp, u_long cmd,
 					msglen = header->size +
 						sizeof(VCHIQ_HEADER_T);
 					/* This must be a VCHIQ-style service */
-					if (pargs->msgbufsize < msglen) {
+					if (args.msgbufsize < msglen) {
 						vchiq_log_error(
 							vchiq_arm_log_level,
 							"header %x: msgbufsize"
 							" %x < msglen %x",
 							(unsigned int)header,
-							pargs->msgbufsize,
+							args.msgbufsize,
 							msglen);
 						WARN(1, "invalid message "
 							"size\n");
@@ -801,7 +882,7 @@ vchiq_ioctl(struct file *fp, u_long cmd,
 					msgbufcount--;
 					if (copy_from_user(&msgbuf,
 						(const void __user *)
-						&pargs->msgbufs[msgbufcount],
+						&args.msgbufs[msgbufcount],
 						sizeof(msgbuf)) != 0) {
 						if (count == 0)
 							ret = -EFAULT;
@@ -826,12 +907,13 @@ vchiq_ioctl(struct file *fp, u_long cmd,
 					completion->header = msgbuf;
 				}
 
-				if (completion->reason ==
-					VCHIQ_SERVICE_CLOSED)
+				if ((completion->reason ==
+					VCHIQ_SERVICE_CLOSED) &&
+					!instance->use_close_delivered)
 					unlock_service(service1);
 
 				if (copy_to_user((void __user *)(
-					(size_t)pargs->buf +
+					(size_t)args.buf +
 					count * sizeof(VCHIQ_COMPLETION_DATA_T)),
 					completion,
 					sizeof(VCHIQ_COMPLETION_DATA_T)) != 0) {
@@ -840,26 +922,31 @@ vchiq_ioctl(struct file *fp, u_long cmd,
 					break;
 				}
 
-				instance->completion_remove++;
+				/* Ensure that the above copy has completed
+				** before advancing the remove pointer. */
+				mb();
+
+				instance->completion_remove = ++remove;
 			}
 
 			pargs->msgbufcount = msgbufcount;
 			pargs->count = count;
 		}
-
 		if (count != 0)
 			up(&instance->remove_event);
+
 		lmutex_unlock(&instance->completion_mutex);
 		DEBUG_TRACE(AWAIT_COMPLETION_LINE);
 	} break;
 
 	case VCHIQ_IOC_DEQUEUE_MESSAGE: {
 		VCHIQ_DEQUEUE_MESSAGE_T *pargs = arg;
+		VCHIQ_DEQUEUE_MESSAGE_T args = *pargs;
 		USER_SERVICE_T *user_service;
 		VCHIQ_HEADER_T *header;
 
 		DEBUG_TRACE(DEQUEUE_MESSAGE_LINE);
-		service = find_service_for_instance(instance, pargs->handle);
+		service = find_service_for_instance(instance, args.handle);
 		if (!service) {
 			ret = -EINVAL;
 			break;
@@ -872,7 +959,7 @@ vchiq_ioctl(struct file *fp, u_long cmd,
 
 		spin_lock(&msg_queue_spinlock);
 		if (user_service->msg_remove == user_service->msg_insert) {
-			if (!pargs->blocking) {
+			if (!args.blocking) {
 				spin_unlock(&msg_queue_spinlock);
 				DEBUG_TRACE(DEQUEUE_MESSAGE_LINE);
 				ret = -EWOULDBLOCK;
@@ -908,10 +995,10 @@ vchiq_ioctl(struct file *fp, u_long cmd,
 		up(&user_service->remove_event);
 		if (header == NULL)
 			ret = -ENOTCONN;
-		else if (header->size <= pargs->bufsize) {
+		else if (header->size <= args.bufsize) {
 			/* Copy to user space if msgbuf is not NULL */
-			if ((pargs->buf == NULL) ||
-				(copy_to_user((void __user *)pargs->buf,
+			if ((args.buf == NULL) ||
+				(copy_to_user((void __user *)args.buf,
 				header->data,
 				header->size) == 0)) {
 				pargs->bufsize = header->size;
@@ -923,7 +1010,7 @@ vchiq_ioctl(struct file *fp, u_long cmd,
 		} else {
 			vchiq_log_error(vchiq_arm_log_level,
 				"header %x: bufsize %x < size %x",
-				(unsigned int)header, pargs->bufsize,
+				(unsigned int)header, args.bufsize,
 				header->size);
 			WARN(1, "invalid size\n");
 			ret = -EMSGSIZE;
@@ -932,23 +1019,24 @@ vchiq_ioctl(struct file *fp, u_long cmd,
 	} break;
 
 	case VCHIQ_IOC_GET_CLIENT_ID: {
-		VCHIQ_SERVICE_HANDLE_T handle = (VCHIQ_SERVICE_HANDLE_T)arg;
+		VCHIQ_SERVICE_HANDLE_T handle = *(VCHIQ_SERVICE_HANDLE_T *)arg;
 
 		ret = vchiq_get_client_id(handle);
 	} break;
 
 	case VCHIQ_IOC_GET_CONFIG: {
 		VCHIQ_GET_CONFIG_T *pargs = arg;
+		VCHIQ_GET_CONFIG_T args = *pargs;
 		VCHIQ_CONFIG_T config;
 
-		if (pargs->config_size > sizeof(config)) {
+		if (args.config_size > sizeof(config)) {
 			ret = -EINVAL;
 			break;
 		}
-		status = vchiq_get_config(instance, pargs->config_size, &config);
+		status = vchiq_get_config(instance, args.config_size, &config);
 		if (status == VCHIQ_SUCCESS) {
-			if (copy_to_user((void __user *)pargs->pconfig,
-				&config, pargs->config_size) != 0) {
+			if (copy_to_user((void __user *)args.pconfig,
+				&config, args.config_size) != 0) {
 				ret = -EFAULT;
 				break;
 			}
@@ -957,15 +1045,16 @@ vchiq_ioctl(struct file *fp, u_long cmd,
 
 	case VCHIQ_IOC_SET_SERVICE_OPTION: {
 		VCHIQ_SET_SERVICE_OPTION_T *pargs = arg;
+		VCHIQ_SET_SERVICE_OPTION_T args = *pargs;
 
-		service = find_service_for_instance(instance, pargs->handle);
+		service = find_service_for_instance(instance, args.handle);
 		if (!service) {
 			ret = -EINVAL;
 			break;
 		}
 
 		status = vchiq_set_service_option(
-				pargs->handle, pargs->option, pargs->value);
+				args.handle, args.option, args.value);
 	} break;
 
 	case VCHIQ_IOC_DUMP_PHYS_MEM: {
@@ -979,6 +1068,28 @@ vchiq_ioctl(struct file *fp, u_long cmd,
 #endif
 	} break;
 
+	case VCHIQ_IOC_LIB_VERSION: {
+		unsigned int lib_version = (unsigned int)arg;
+
+		if (lib_version < VCHIQ_VERSION_MIN)
+			ret = -EINVAL;
+		else if (lib_version >= VCHIQ_VERSION_CLOSE_DELIVERED)
+			instance->use_close_delivered = 1;
+	} break;
+
+	case VCHIQ_IOC_CLOSE_DELIVERED: {
+		VCHIQ_SERVICE_HANDLE_T handle = *(VCHIQ_SERVICE_HANDLE_T *)arg;
+
+		service = find_closed_service_for_instance(instance, handle);
+		if (service != NULL) {
+			USER_SERVICE_T *user_service =
+				(USER_SERVICE_T *)service->base.userdata;
+			close_delivered(user_service);
+		}
+		else
+			ret = -EINVAL;
+	} break;
+
 	default:
 		ret = -ENOTTY;
 		break;
@@ -1019,15 +1130,6 @@ vchiq_ioctl(struct file *fp, u_long cmd,
 	return ret;
 }
 
-#if notyet
-static void
-instance_dtr(void *data)
-{
-
-   free(data, M_VCHIQ);
-}
-#endif
-
 /****************************************************************************
 *
 *   vchiq_open
@@ -1067,7 +1169,7 @@ vchiq_open(dev_t dev, int flags, int mod
 		instance->pid = current->l_proc->p_pid;
 
 #ifdef notyet
-		ret = vchiq_proc_add_instance(instance);
+		ret = vchiq_debugfs_add_instance(instance);
 		if (ret != 0) {
 			kfree(instance);
 			return ret;
@@ -1101,13 +1203,11 @@ vchiq_close(struct file *fp)
 {
 	int ret = 0;
 	if (1) {
-		VCHIQ_INSTANCE_T instance;
+		VCHIQ_INSTANCE_T instance = fp->f_data;
 		VCHIQ_STATE_T *state = vchiq_get_state();
 		VCHIQ_SERVICE_T *service;
 		int i;
 
-		instance = fp->f_data;
-
 		vchiq_log_info(vchiq_arm_log_level,
 			"vchiq_release: instance=%lx",
 			(unsigned long)instance);
@@ -1187,7 +1287,15 @@ vchiq_close(struct file *fp)
 				(MAX_COMPLETIONS - 1)];
 			service1 = completion->service_userdata;
 			if (completion->reason == VCHIQ_SERVICE_CLOSED)
+			{
+				USER_SERVICE_T *user_service =
+					service->base.userdata;
+
+				/* Wake any blocked user-thread */
+				if (instance->use_close_delivered)
+					up(&user_service->close_event);
 				unlock_service(service1);
+			}
 			instance->completion_remove++;
 		}
 
@@ -1458,7 +1566,7 @@ vchiq_read(struct file *file, off_t *ppo
 
 	result = uiomove(buf, context.actual, uio);
 	kmem_free(buf, PAGE_SIZE);
-	
+
 	return result;
 }
 
@@ -1591,6 +1699,8 @@ exit:
 	return 0;
 }
 
+
+
 VCHIQ_STATUS_T
 vchiq_arm_init_state(VCHIQ_STATE_T *state, VCHIQ_ARM_STATE_T *arm_state)
 {
@@ -1710,7 +1820,7 @@ set_suspend_state(VCHIQ_ARM_STATE_T *arm
 		complete_all(&arm_state->vc_resume_complete);
 		break;
 	case VC_SUSPEND_IDLE:
-		INIT_COMPLETION(arm_state->vc_suspend_complete);
+		reinit_completion(&arm_state->vc_suspend_complete);
 		break;
 	case VC_SUSPEND_REQUESTED:
 		break;
@@ -1738,7 +1848,7 @@ set_resume_state(VCHIQ_ARM_STATE_T *arm_
 	case VC_RESUME_FAILED:
 		break;
 	case VC_RESUME_IDLE:
-		INIT_COMPLETION(arm_state->vc_resume_complete);
+		reinit_completion(&arm_state->vc_resume_complete);
 		break;
 	case VC_RESUME_REQUESTED:
 		break;
@@ -1800,7 +1910,7 @@ block_resume(VCHIQ_ARM_STATE_T *arm_stat
 	 * (which only happens when blocked_count hits 0) then those threads
 	 * will have to wait until next time around */
 	if (arm_state->blocked_count) {
-		INIT_COMPLETION(arm_state->blocked_blocker);
+		reinit_completion(&arm_state->blocked_blocker);
 		write_unlock_bh(&arm_state->susp_res_lock);
 		vchiq_log_info(vchiq_susp_log_level, "%s wait for previously "
 			"blocked clients", __func__);
@@ -1845,7 +1955,7 @@ block_resume(VCHIQ_ARM_STATE_T *arm_stat
 		write_lock_bh(&arm_state->susp_res_lock);
 		resume_count++;
 	}
-	INIT_COMPLETION(arm_state->resume_blocker);
+	reinit_completion(&arm_state->resume_blocker);
 	arm_state->resume_blocked = 1;
 
 out:
@@ -2456,6 +2566,54 @@ vchiq_release_service_internal(VCHIQ_SER
 	return vchiq_release_internal(service->state, service);
 }
 
+#ifdef notyet
+VCHIQ_DEBUGFS_NODE_T *
+vchiq_instance_get_debugfs_node(VCHIQ_INSTANCE_T instance)
+{
+	return &instance->debugfs_node;
+}
+
+int
+vchiq_instance_get_use_count(VCHIQ_INSTANCE_T instance)
+{
+	VCHIQ_SERVICE_T *service;
+	int use_count = 0, i;
+	i = 0;
+	while ((service = next_service_by_instance(instance->state,
+		instance, &i)) != NULL) {
+		use_count += service->service_use_count;
+		unlock_service(service);
+	}
+	return use_count;
+}
+
+int
+vchiq_instance_get_pid(VCHIQ_INSTANCE_T instance)
+{
+	return instance->pid;
+}
+
+int
+vchiq_instance_get_trace(VCHIQ_INSTANCE_T instance)
+{
+	return instance->trace;
+}
+
+void
+vchiq_instance_set_trace(VCHIQ_INSTANCE_T instance, int trace)
+{
+	VCHIQ_SERVICE_T *service;
+	int i;
+	i = 0;
+	while ((service = next_service_by_instance(instance->state,
+		instance, &i)) != NULL) {
+		service->trace = trace;
+		unlock_service(service);
+	}
+	instance->trace = (trace != 0);
+}
+#endif
+
 static void suspend_timer_callback(unsigned long context)
 {
 	VCHIQ_STATE_T *state = (VCHIQ_STATE_T *)context;
@@ -2658,6 +2816,7 @@ void vchiq_platform_conn_state_changed(V
 	}
 }
 
+
 /****************************************************************************
 *
 *   vchiq_init - called when the module is loaded.
@@ -2694,73 +2853,6 @@ failed_platform_init:
 	return err;
 }
 
-#ifdef notyet
-static int vchiq_instance_get_use_count(VCHIQ_INSTANCE_T instance)
-{
-	VCHIQ_SERVICE_T *service;
-	int use_count = 0, i;
-	i = 0;
-	while ((service = next_service_by_instance(instance->state,
-		instance, &i)) != NULL) {
-		use_count += service->service_use_count;
-		unlock_service(service);
-	}
-	return use_count;
-}
-
-/* read the per-process use-count */
-static int proc_read_use_count(char *page, char **start,
-			       off_t off, int count,
-			       int *eof, void *data)
-{
-	VCHIQ_INSTANCE_T instance = data;
-	int len, use_count;
-
-	use_count = vchiq_instance_get_use_count(instance);
-	len = snprintf(page+off, count, "%d\n", use_count);
-
-	return len;
-}
-
-/* add an instance (process) to the proc entries */
-static int vchiq_proc_add_instance(VCHIQ_INSTANCE_T instance)
-{
-	char pidstr[32];
-	struct proc_dir_entry *top, *use_count;
-	struct proc_dir_entry *clients = vchiq_clients_top();
-	int pid = instance->pid;
-
-	snprintf(pidstr, sizeof(pidstr), "%d", pid);
-	top = proc_mkdir(pidstr, clients);
-	if (!top)
-		goto fail_top;
-
-	use_count = create_proc_read_entry("use_count",
-					   0444, top,
-					   proc_read_use_count,
-					   instance);
-	if (!use_count)
-		goto fail_use_count;
-
-	instance->proc_entry = top;
-
-	return 0;
-
-fail_use_count:
-	remove_proc_entry(top->name, clients);
-fail_top:
-	return -ENOMEM;
-}
-
-static void vchiq_proc_remove_instance(VCHIQ_INSTANCE_T instance)
-{
-	struct proc_dir_entry *clients = vchiq_clients_top();
-	remove_proc_entry("use_count", instance->proc_entry);
-	remove_proc_entry(instance->proc_entry->name, clients);
-}
-
-#endif
-
 /****************************************************************************
 *
 *   vchiq_exit - called when the module is unloaded.

Index: src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_core.c
diff -u src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_core.c:1.10 src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_core.c:1.11
--- src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_core.c:1.10	Sat Dec 20 19:49:27 2014
+++ src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_core.c	Thu Jan 12 05:41:25 2017
@@ -47,9 +47,12 @@
 #define SLOT_QUEUE_INDEX_FROM_POS(pos) \
 	((int)((unsigned int)(pos) / VCHIQ_SLOT_SIZE))
 
-
 #define BULK_INDEX(x) (x & (VCHIQ_NUM_SERVICE_BULKS - 1))
 
+#define SRVTRACE_LEVEL(srv) \
+	(((srv) && (srv)->trace) ? VCHIQ_LOG_TRACE : vchiq_core_msg_log_level)
+#define SRVTRACE_ENABLED(srv, lev) \
+	(((srv) && (srv)->trace) || (vchiq_core_msg_log_level >= (lev)))
 
 struct vchiq_open_payload {
 	int fourcc;
@@ -62,6 +65,13 @@ struct vchiq_openack_payload {
 	short version;
 };
 
+enum
+{
+	QMFLAGS_IS_BLOCKING     = (1 << 0),
+	QMFLAGS_NO_MUTEX_LOCK   = (1 << 1),
+	QMFLAGS_NO_MUTEX_UNLOCK = (1 << 2)
+};
+
 /* we require this for consistency between endpoints */
 vchiq_static_assert(sizeof(VCHIQ_HEADER_T) == 8);
 vchiq_static_assert(IS_POW2(sizeof(VCHIQ_HEADER_T)));
@@ -231,6 +241,31 @@ find_service_for_instance(VCHIQ_INSTANCE
 }
 
 VCHIQ_SERVICE_T *
+find_closed_service_for_instance(VCHIQ_INSTANCE_T instance,
+	VCHIQ_SERVICE_HANDLE_T handle) {
+	VCHIQ_SERVICE_T *service;
+
+	spin_lock(&service_spinlock);
+	service = handle_to_service(handle);
+	if (service &&
+		((service->srvstate == VCHIQ_SRVSTATE_FREE) ||
+		 (service->srvstate == VCHIQ_SRVSTATE_CLOSED)) &&
+		(service->handle == handle) &&
+		(service->instance == instance)) {
+		BUG_ON(service->ref_count == 0);
+		service->ref_count++;
+	} else
+		service = NULL;
+	spin_unlock(&service_spinlock);
+
+	if (!service)
+		vchiq_log_info(vchiq_core_log_level,
+			"Invalid service handle 0x%x", handle);
+
+	return service;
+}
+
+VCHIQ_SERVICE_T *
 next_service_by_instance(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance,
 	int *pidx)
 {
@@ -586,15 +621,15 @@ process_free_queue(VCHIQ_STATE_T *state)
 	BITSET_T service_found[BITSET_SIZE(VCHIQ_MAX_SERVICES)];
 	int slot_queue_available;
 
-	/* Use a read memory barrier to ensure that any state that may have
-	** been modified by another thread is not masked by stale prefetched
-	** values. */
-	rmb();
-
 	/* Find slots which have been freed by the other side, and return them
 	** to the available queue. */
 	slot_queue_available = state->slot_queue_available;
 
+	/* Use a memory barrier to ensure that any state that may have been
+	** modified by another thread is not masked by stale prefetched
+	** values. */
+	mb();
+
 	while (slot_queue_available != local->slot_queue_recycle) {
 		unsigned int pos;
 		int slot_index = local->slot_queue[slot_queue_available++ &
@@ -602,6 +637,8 @@ process_free_queue(VCHIQ_STATE_T *state)
 		char *data = (char *)SLOT_DATA_FROM_INDEX(state, slot_index);
 		int data_found = 0;
 
+		rmb();
+
 		vchiq_log_trace(vchiq_core_log_level, "%d: pfq %d=%x %x %x",
 			state->id, slot_index, (unsigned int)data,
 			local->slot_queue_recycle, slot_queue_available);
@@ -717,6 +754,8 @@ process_free_queue(VCHIQ_STATE_T *state)
 				up(&state->data_quota_event);
 		}
 
+		mb();
+
 		state->slot_queue_available = slot_queue_available;
 		up(&state->slot_available_event);
 	}
@@ -726,7 +765,7 @@ process_free_queue(VCHIQ_STATE_T *state)
 static VCHIQ_STATUS_T
 queue_message(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service,
 	int msgid, const VCHIQ_ELEMENT_T *elements,
-	int count, int size, int is_blocking)
+	int count, int size, int flags)
 {
 	VCHIQ_SHARED_STATE_T *local;
 	VCHIQ_SERVICE_QUOTA_T *service_quota = NULL;
@@ -741,7 +780,7 @@ queue_message(VCHIQ_STATE_T *state, VCHI
 
 	WARN_ON(!(stride <= VCHIQ_SLOT_SIZE));
 
-	if ((type != VCHIQ_MSG_RESUME) &&
+	if (!(flags & QMFLAGS_NO_MUTEX_LOCK) &&
 		(lmutex_lock_interruptible(&state->slot_mutex) != 0))
 		return VCHIQ_RETRY;
 
@@ -749,6 +788,8 @@ queue_message(VCHIQ_STATE_T *state, VCHI
 		int tx_end_index;
 
 		BUG_ON(!service);
+		BUG_ON((flags & (QMFLAGS_NO_MUTEX_LOCK |
+				 QMFLAGS_NO_MUTEX_UNLOCK)) != 0);
 
 		if (service->closing) {
 			/* The service has been closed */
@@ -824,12 +865,15 @@ queue_message(VCHIQ_STATE_T *state, VCHI
 		spin_unlock(&quota_spinlock);
 	}
 
-	header = reserve_space(state, stride, is_blocking);
+	header = reserve_space(state, stride, flags & QMFLAGS_IS_BLOCKING);
 
 	if (!header) {
 		if (service)
 			VCHIQ_SERVICE_STATS_INC(service, slot_stalls);
-		lmutex_unlock(&state->slot_mutex);
+		/* In the event of a failure, return the mutex to the
+		   state it was in */
+		if (!(flags & QMFLAGS_NO_MUTEX_LOCK))
+			lmutex_unlock(&state->slot_mutex);
 		return VCHIQ_RETRY;
 	}
 
@@ -847,6 +891,8 @@ queue_message(VCHIQ_STATE_T *state, VCHI
 			VCHIQ_MSG_DSTPORT(msgid));
 
 		BUG_ON(!service);
+		BUG_ON((flags & (QMFLAGS_NO_MUTEX_LOCK |
+				 QMFLAGS_NO_MUTEX_UNLOCK)) != 0);
 
 		for (i = 0, pos = 0; i < (unsigned int)count;
 			pos += elements[i++].size)
@@ -860,16 +906,14 @@ queue_message(VCHIQ_STATE_T *state, VCHI
 						error_count);
 					return VCHIQ_ERROR;
 				}
-				if (i == 0) {
-					if (vchiq_core_msg_log_level >=
-						VCHIQ_LOG_INFO)
-						vchiq_log_dump_mem("Sent", 0,
-							header->data + pos,
-							min(64,
-							elements[0].size));
-				}
 			}
 
+		if (SRVTRACE_ENABLED(service,
+				VCHIQ_LOG_INFO))
+			vchiq_log_dump_mem("Sent", 0,
+				header->data,
+				min(16, pos));
+
 		spin_lock(&quota_spinlock);
 		service_quota->message_use_count++;
 
@@ -928,7 +972,7 @@ queue_message(VCHIQ_STATE_T *state, VCHI
 			? service->base.fourcc
 			: VCHIQ_MAKE_FOURCC('?', '?', '?', '?');
 
-		vchiq_log_info(vchiq_core_msg_log_level,
+		vchiq_log_info(SRVTRACE_LEVEL(service),
 			"Sent Msg %s(%u) to %c%c%c%c s:%u d:%d len:%d",
 			msg_type_str(VCHIQ_MSG_TYPE(msgid)),
 			VCHIQ_MSG_TYPE(msgid),
@@ -948,7 +992,7 @@ queue_message(VCHIQ_STATE_T *state, VCHI
 	if (service && (type == VCHIQ_MSG_CLOSE))
 		vchiq_set_service_state(service, VCHIQ_SRVSTATE_CLOSESENT);
 
-	if (VCHIQ_MSG_TYPE(msgid) != VCHIQ_MSG_PAUSE)
+	if (!(flags & QMFLAGS_NO_MUTEX_UNLOCK))
 		lmutex_unlock(&state->slot_mutex);
 
 	remote_event_signal(&state->remote->trigger);
@@ -1008,16 +1052,13 @@ queue_message_sync(VCHIQ_STATE_T *state,
 						error_count);
 					return VCHIQ_ERROR;
 				}
-				if (i == 0) {
-					if (vchiq_sync_log_level >=
-						VCHIQ_LOG_TRACE)
-						vchiq_log_dump_mem("Sent Sync",
-							0, header->data + pos,
-							min(64,
-							elements[0].size));
-				}
 			}
 
+		if (vchiq_sync_log_level >= VCHIQ_LOG_TRACE)
+			vchiq_log_dump_mem("Sent Sync",
+				0, header->data,
+				min(16, pos));
+
 		VCHIQ_SERVICE_STATS_INC(service, ctrl_tx_count);
 		VCHIQ_SERVICE_STATS_ADD(service, ctrl_tx_bytes, size);
 	} else {
@@ -1320,11 +1361,11 @@ resolve_bulks(VCHIQ_SERVICE_T *service, 
 		vchiq_transfer_bulk(bulk);
 		lmutex_unlock(&state->bulk_transfer_mutex);
 
-		if (vchiq_core_msg_log_level >= VCHIQ_LOG_INFO) {
+		if (SRVTRACE_ENABLED(service, VCHIQ_LOG_INFO)) {
 			const char *header = (queue == &service->bulk_tx) ?
 				"Send Bulk to" : "Recv Bulk from";
 			if (bulk->actual != VCHIQ_BULK_ACTUAL_ABORTED)
-				vchiq_log_info(vchiq_core_msg_log_level,
+				vchiq_log_info(SRVTRACE_LEVEL(service),
 					"%s %c%c%c%c d:%d len:%d %x<->%x",
 					header,
 					VCHIQ_FOURCC_AS_4CHARS(
@@ -1334,7 +1375,7 @@ resolve_bulks(VCHIQ_SERVICE_T *service, 
 					(unsigned int)bulk->data,
 					(unsigned int)bulk->remote_data);
 			else
-				vchiq_log_info(vchiq_core_msg_log_level,
+				vchiq_log_info(SRVTRACE_LEVEL(service),
 					"%s %c%c%c%c d:%d ABORTED - tx len:%d,"
 					" rx len:%d %x<->%x",
 					header,
@@ -1381,7 +1422,7 @@ abort_outstanding_bulks(VCHIQ_SERVICE_T 
 		if (queue->process != queue->local_insert) {
 			vchiq_complete_bulk(bulk);
 
-			vchiq_log_info(vchiq_core_msg_log_level,
+			vchiq_log_info(SRVTRACE_LEVEL(service),
 				"%s %c%c%c%c d:%d ABORTED - tx len:%d, "
 				"rx len:%d",
 				is_tx ? "Send Bulk to" : "Recv Bulk from",
@@ -1516,8 +1557,14 @@ parse_open(VCHIQ_STATE_T *state, VCHIQ_H
 					sizeof(ack_payload)
 				};
 
+				if (state->version_common <
+				    VCHIQ_VERSION_SYNCHRONOUS_MODE)
+					service->sync = 0;
+
 				/* Acknowledge the OPEN */
-				if (service->sync) {
+				if (service->sync &&
+				    (state->version_common >=
+				     VCHIQ_VERSION_SYNCHRONOUS_MODE)) {
 					if (queue_message_sync(state, NULL,
 						VCHIQ_MAKE_MSG(
 							VCHIQ_MSG_OPENACK,
@@ -1631,9 +1678,11 @@ parse_rx_slots(VCHIQ_STATE_T *state)
 		case VCHIQ_MSG_BULK_RX_DONE:
 		case VCHIQ_MSG_BULK_TX_DONE:
 			service = find_service_by_port(state, localport);
-			if ((!service || service->remoteport != remoteport) &&
-				(localport == 0) &&
-				(type == VCHIQ_MSG_CLOSE)) {
+			if ((!service ||
+			     ((service->remoteport != remoteport) &&
+			      (service->remoteport != VCHIQ_PORT_FREE))) &&
+			    (localport == 0) &&
+			    (type == VCHIQ_MSG_CLOSE)) {
 				/* This could be a CLOSE from a client which
 				   hadn't yet received the OPENACK - look for
 				   the connected service */
@@ -1665,13 +1714,13 @@ parse_rx_slots(VCHIQ_STATE_T *state)
 			break;
 		}
 
-		if (vchiq_core_msg_log_level >= VCHIQ_LOG_INFO) {
+		if (SRVTRACE_ENABLED(service, VCHIQ_LOG_INFO)) {
 			int svc_fourcc;
 
 			svc_fourcc = service
 				? service->base.fourcc
 				: VCHIQ_MAKE_FOURCC('?', '?', '?', '?');
-			vchiq_log_info(vchiq_core_msg_log_level,
+			vchiq_log_info(SRVTRACE_LEVEL(service),
 				"Rcvd Msg %s(%u) from %c%c%c%c s:%d d:%d "
 				"len:%d",
 				msg_type_str(type), type,
@@ -1679,7 +1728,7 @@ parse_rx_slots(VCHIQ_STATE_T *state)
 				remoteport, localport, size);
 			if (size > 0)
 				vchiq_log_dump_mem("Rcvd", 0, header->data,
-					min(64, size));
+					min(16, size));
 		}
 
 		if (((unsigned int)header & VCHIQ_SLOT_MASK) + calc_stride(size)
@@ -1741,7 +1790,7 @@ parse_rx_slots(VCHIQ_STATE_T *state)
 				service->remoteport);
 			break;
 		case VCHIQ_MSG_DATA:
-			vchiq_log_trace(vchiq_core_log_level,
+			vchiq_log_info(vchiq_core_log_level,
 				"%d: prs DATA@%x,%x (%d->%d)",
 				state->id, (unsigned int)header, size,
 				remoteport, localport);
@@ -1769,6 +1818,8 @@ parse_rx_slots(VCHIQ_STATE_T *state)
 			vchiq_log_info(vchiq_core_log_level,
 				"%d: prs CONNECT@%x",
 				state->id, (unsigned int)header);
+			state->version_common = ((VCHIQ_SLOT_ZERO_T *)
+						 state->slot_data)->version;
 			up(&state->connect);
 			break;
 		case VCHIQ_MSG_BULK_RX:
@@ -1922,7 +1973,8 @@ parse_rx_slots(VCHIQ_STATE_T *state)
 				/* Send a PAUSE in response */
 				if (queue_message(state, NULL,
 					VCHIQ_MAKE_MSG(VCHIQ_MSG_PAUSE, 0, 0),
-					NULL, 0, 0, 0) == VCHIQ_RETRY)
+					NULL, 0, 0, QMFLAGS_NO_MUTEX_UNLOCK)
+				    == VCHIQ_RETRY)
 					goto bail_not_ready;
 				if (state->is_master)
 					pause_bulks(state);
@@ -1985,8 +2037,8 @@ bail_not_ready:
 }
 
 /* Called by the slot handler thread */
-int slot_handler_func(void *v);
-int
+static int slot_handler_func(void *v);
+static int
 slot_handler_func(void *v)
 {
 	VCHIQ_STATE_T *state = (VCHIQ_STATE_T *) v;
@@ -2021,7 +2073,9 @@ slot_handler_func(void *v)
 					pause_bulks(state);
 				if (queue_message(state, NULL,
 					VCHIQ_MAKE_MSG(VCHIQ_MSG_PAUSE, 0, 0),
-					NULL, 0, 0, 0) != VCHIQ_RETRY) {
+					NULL, 0, 0,
+					QMFLAGS_NO_MUTEX_UNLOCK)
+				    != VCHIQ_RETRY) {
 					vchiq_set_conn_state(state,
 						VCHIQ_CONNSTATE_PAUSE_SENT);
 				} else {
@@ -2039,7 +2093,8 @@ slot_handler_func(void *v)
 			case VCHIQ_CONNSTATE_RESUMING:
 				if (queue_message(state, NULL,
 					VCHIQ_MAKE_MSG(VCHIQ_MSG_RESUME, 0, 0),
-					NULL, 0, 0, 0) != VCHIQ_RETRY) {
+					NULL, 0, 0, QMFLAGS_NO_MUTEX_LOCK)
+					!= VCHIQ_RETRY) {
 					if (state->is_master)
 						resume_bulks(state);
 					vchiq_set_conn_state(state,
@@ -2075,8 +2130,8 @@ slot_handler_func(void *v)
 
 
 /* Called by the recycle thread */
-int recycle_func(void *v);
-int
+static int recycle_func(void *v);
+static int
 recycle_func(void *v)
 {
 	VCHIQ_STATE_T *state = (VCHIQ_STATE_T *) v;
@@ -2092,8 +2147,8 @@ recycle_func(void *v)
 
 
 /* Called by the sync thread */
-int sync_func(void *v);
-int
+static int sync_func(void *v);
+static int
 sync_func(void *v)
 {
 	VCHIQ_STATE_T *state = (VCHIQ_STATE_T *) v;
@@ -2143,7 +2198,7 @@ sync_func(void *v)
 				remoteport, localport, size);
 			if (size > 0)
 				vchiq_log_dump_mem("Rcvd", 0, header->data,
-					min(64, size));
+					min(16, size));
 		}
 
 		switch (type) {
@@ -2162,6 +2217,7 @@ sync_func(void *v)
 				service->remoteport = remoteport;
 				vchiq_set_service_state(service,
 					VCHIQ_SRVSTATE_OPENSYNC);
+				service->sync = 1;
 				up(&service->remove_event);
 			}
 			release_message_sync(state, header);
@@ -2270,6 +2326,10 @@ vchiq_init_state(VCHIQ_STATE_T *state, V
 	static int id;
 	int i;
 
+	vchiq_log_warning(vchiq_core_log_level,
+		"%s: slot_zero = 0x%08lx, is_master = %d",
+		__func__, (unsigned long)slot_zero, is_master);
+
 	/* Check the input configuration */
 
 	if (slot_zero->magic != VCHIQ_MAGIC) {
@@ -2341,6 +2401,9 @@ vchiq_init_state(VCHIQ_STATE_T *state, V
 		return VCHIQ_ERROR;
 	}
 
+	if (VCHIQ_VERSION < slot_zero->version)
+		slot_zero->version = VCHIQ_VERSION;
+
 	if (is_master) {
 		local = &slot_zero->master;
 		remote = &slot_zero->slave;
@@ -2380,6 +2443,10 @@ vchiq_init_state(VCHIQ_STATE_T *state, V
 
 	_sema_init(&state->connect, 0);
 	lmutex_init(&state->mutex);
+	_sema_init(&state->trigger_event, 0);
+	_sema_init(&state->recycle_event, 0);
+	_sema_init(&state->sync_trigger_event, 0);
+	_sema_init(&state->sync_release_event, 0);
 
 	lmutex_init(&state->slot_mutex);
 	lmutex_init(&state->recycle_mutex);
@@ -2513,6 +2580,7 @@ vchiq_add_service_internal(VCHIQ_STATE_T
 		service->auto_close    = 1;
 		service->sync          = 0;
 		service->closing       = 0;
+		service->trace         = 0;
 		atomic_set(&service->poll_flags, 0);
 		service->version       = params->version;
 		service->version_min   = params->version_min;
@@ -2643,8 +2711,9 @@ vchiq_open_service_internal(VCHIQ_SERVIC
 	vchiq_use_service_internal(service);
 	status = queue_message(service->state, NULL,
 		VCHIQ_MAKE_MSG(VCHIQ_MSG_OPEN, service->localport, 0),
-		&body, 1, sizeof(payload), 1);
+		&body, 1, sizeof(payload), QMFLAGS_IS_BLOCKING);
 	if (status == VCHIQ_SUCCESS) {
+		/* Wait for the ACK/NAK */
 		if (down_interruptible(&service->remove_event) != 0) {
 			status = VCHIQ_RETRY;
 			vchiq_release_service_internal(service);
@@ -2671,7 +2740,18 @@ release_service_messages(VCHIQ_SERVICE_T
 	int slot_last = state->remote->slot_last;
 	int i;
 
-	/* Release any claimed messages */
+	/* Release any claimed messages aimed at this service */
+
+	if (service->sync) {
+		VCHIQ_HEADER_T *header =
+			(VCHIQ_HEADER_T *)SLOT_DATA_FROM_INDEX(state,
+						state->remote->slot_sync);
+		if (VCHIQ_MSG_DSTPORT(header->msgid) == service->localport)
+			release_message_sync(state, header);
+
+		return;
+	}
+
 	for (i = state->remote->slot_first; i <= slot_last; i++) {
 		VCHIQ_SLOT_INFO_T *slot_info =
 			SLOT_INFO_FROM_INDEX(state, i);
@@ -2869,17 +2949,31 @@ vchiq_close_service_internal(VCHIQ_SERVI
 				(VCHIQ_MSG_CLOSE,
 				service->localport,
 				VCHIQ_MSG_DSTPORT(service->remoteport)),
-				NULL, 0, 0, 0);
+				NULL, 0, 0, QMFLAGS_NO_MUTEX_UNLOCK);
 
 		if (status == VCHIQ_SUCCESS) {
-			if (!close_recvd)
+			if (!close_recvd) {
+				/* Change the state while the mutex is
+				   still held */
+				vchiq_set_service_state(service,
+							VCHIQ_SRVSTATE_CLOSESENT);
+				lmutex_unlock(&state->slot_mutex);
+				if (service->sync)
+					lmutex_unlock(&state->sync_mutex);
 				break;
+			}
 		} else if (service->srvstate == VCHIQ_SRVSTATE_OPENSYNC) {
 			lmutex_unlock(&state->sync_mutex);
 			break;
 		} else
 			break;
 
+		/* Change the state while the mutex is still held */
+		vchiq_set_service_state(service, VCHIQ_SRVSTATE_CLOSERECVD);
+		lmutex_unlock(&state->slot_mutex);
+		if (service->sync)
+			lmutex_unlock(&state->sync_mutex);
+
 		status = close_service_complete(service,
 				VCHIQ_SRVSTATE_CLOSERECVD);
 		break;
@@ -2986,7 +3080,7 @@ vchiq_connect_internal(VCHIQ_STATE_T *st
 	if (state->conn_state == VCHIQ_CONNSTATE_DISCONNECTED) {
 		if (queue_message(state, NULL,
 			VCHIQ_MAKE_MSG(VCHIQ_MSG_CONNECT, 0, 0), NULL, 0,
-			0, 1) == VCHIQ_RETRY)
+			0, QMFLAGS_IS_BLOCKING) == VCHIQ_RETRY)
 			return VCHIQ_RETRY;
 
 		vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTING);
@@ -3272,6 +3366,16 @@ vchiq_bulk_transfer(VCHIQ_SERVICE_HANDLE
 		service->localport, service->remoteport, dir_char,
 		size, (unsigned int)bulk->data, (unsigned int)userdata);
 
+	/* The slot mutex must be held when the service is being closed, so
+	   claim it here to ensure that isn't happening */
+	if (lmutex_lock_interruptible(&state->slot_mutex) != 0) {
+		status = VCHIQ_RETRY;
+		goto cancel_bulk_error_exit;
+	}
+
+	if (service->srvstate != VCHIQ_SRVSTATE_OPEN)
+		goto unlock_both_error_exit;
+
 	if (state->is_master) {
 		queue->local_insert++;
 		if (resolve_bulks(service, queue))
@@ -3285,14 +3389,17 @@ vchiq_bulk_transfer(VCHIQ_SERVICE_HANDLE
 		status = queue_message(state, NULL,
 			VCHIQ_MAKE_MSG(dir_msgtype,
 				service->localport, service->remoteport),
-			&element, 1, sizeof(payload), 1);
+			&element, 1, sizeof(payload),
+			QMFLAGS_IS_BLOCKING |
+			QMFLAGS_NO_MUTEX_LOCK |
+			QMFLAGS_NO_MUTEX_UNLOCK);
 		if (status != VCHIQ_SUCCESS) {
-			vchiq_complete_bulk(bulk);
-			goto unlock_error_exit;
+			goto unlock_both_error_exit;
 		}
 		queue->local_insert++;
 	}
 
+	lmutex_unlock(&state->slot_mutex);
 	lmutex_unlock(&service->bulk_mutex);
 
 	vchiq_log_trace(vchiq_core_log_level,
@@ -3316,6 +3423,10 @@ waiting:
 
 	return status;
 
+unlock_both_error_exit:
+	lmutex_unlock(&state->slot_mutex);
+cancel_bulk_error_exit:
+	vchiq_complete_bulk(bulk);
 unlock_error_exit:
 	lmutex_unlock(&service->bulk_mutex);
 
@@ -3526,6 +3637,11 @@ vchiq_set_service_option(VCHIQ_SERVICE_H
 			}
 			break;
 
+		case VCHIQ_SERVICE_OPTION_TRACE:
+			service->trace = value;
+			status = VCHIQ_SUCCESS;
+			break;
+
 		default:
 			break;
 		}

Index: src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_core.h
diff -u src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_core.h:1.3 src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_core.h:1.4
--- src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_core.h:1.3	Thu Mar 27 23:03:07 2014
+++ src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_core.h	Thu Jan 12 05:41:25 2017
@@ -55,22 +55,22 @@
 #ifndef vchiq_log_error
 #define vchiq_log_error(cat, fmt, ...) \
 	do { if (cat >= VCHIQ_LOG_ERROR) \
-		printf(VCHIQ_LOG_PREFIX fmt "\n", ##__VA_ARGS__); } while (0)
+		printf_tolog(VCHIQ_LOG_PREFIX fmt "\n", ##__VA_ARGS__); } while (0)
 #endif
 #ifndef vchiq_log_warning
 #define vchiq_log_warning(cat, fmt, ...) \
 	do { if (cat >= VCHIQ_LOG_WARNING) \
-		 printf(VCHIQ_LOG_PREFIX fmt "\n", ##__VA_ARGS__); } while (0)
+		 printf_tolog(VCHIQ_LOG_PREFIX fmt "\n", ##__VA_ARGS__); } while (0)
 #endif
 #ifndef vchiq_log_info
 #define vchiq_log_info(cat, fmt, ...) \
 	do { if (cat >= VCHIQ_LOG_INFO) \
-		printf(VCHIQ_LOG_PREFIX fmt "\n", ##__VA_ARGS__); } while (0)
+		printf_tolog(VCHIQ_LOG_PREFIX fmt "\n", ##__VA_ARGS__); } while (0)
 #endif
 #ifndef vchiq_log_trace
 #define vchiq_log_trace(cat, fmt, ...) \
 	do { if (cat >= VCHIQ_LOG_TRACE) \
-		printf(VCHIQ_LOG_PREFIX fmt "\n", ##__VA_ARGS__); } while (0)
+		printf_tolog(VCHIQ_LOG_PREFIX fmt "\n", ##__VA_ARGS__); } while (0)
 #endif
 
 #define vchiq_loud_error(...) \
@@ -295,6 +295,7 @@ typedef struct vchiq_service_struct {
 	char auto_close;
 	char sync;
 	char closing;
+	char trace;
 	atomic_t poll_flags;
 	short version;
 	short version_min;
@@ -402,6 +403,7 @@ struct vchiq_state_struct {
 	int initialised;
 	VCHIQ_CONNSTATE_T conn_state;
 	int is_master;
+	short version_common;
 
 	VCHIQ_SHARED_STATE_T *local;
 	VCHIQ_SHARED_STATE_T *remote;
@@ -606,6 +608,10 @@ find_service_for_instance(VCHIQ_INSTANCE
 	VCHIQ_SERVICE_HANDLE_T handle);
 
 extern VCHIQ_SERVICE_T *
+find_closed_service_for_instance(VCHIQ_INSTANCE_T instance,
+	VCHIQ_SERVICE_HANDLE_T handle);
+
+extern VCHIQ_SERVICE_T *
 next_service_by_instance(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance,
 	int *pidx);
 

Index: src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_if.h
diff -u src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_if.h:1.2 src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_if.h:1.3
--- src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_if.h:1.2	Thu Mar 27 23:03:07 2014
+++ src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_if.h	Thu Jan 12 05:41:25 2017
@@ -74,7 +74,8 @@ typedef enum {
 	VCHIQ_SERVICE_OPTION_AUTOCLOSE,
 	VCHIQ_SERVICE_OPTION_SLOT_QUOTA,
 	VCHIQ_SERVICE_OPTION_MESSAGE_QUOTA,
-	VCHIQ_SERVICE_OPTION_SYNCHRONOUS
+	VCHIQ_SERVICE_OPTION_SYNCHRONOUS,
+	VCHIQ_SERVICE_OPTION_TRACE
 } VCHIQ_SERVICE_OPTION_T;
 
 typedef struct vchiq_header_struct {
Index: src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_ioctl.h
diff -u src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_ioctl.h:1.2 src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_ioctl.h:1.3
--- src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_ioctl.h:1.2	Thu Mar 27 23:03:07 2014
+++ src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_ioctl.h	Thu Jan 12 05:41:25 2017
@@ -123,6 +123,8 @@ typedef struct {
 	_IOW(VCHIQ_IOC_MAGIC,  14, VCHIQ_SET_SERVICE_OPTION_T)
 #define VCHIQ_IOC_DUMP_PHYS_MEM \
 	_IOW(VCHIQ_IOC_MAGIC,  15, VCHIQ_DUMP_MEM_T)
-#define VCHIQ_IOC_MAX                  15
+#define VCHIQ_IOC_LIB_VERSION          _IO(VCHIQ_IOC_MAGIC,   16)
+#define VCHIQ_IOC_CLOSE_DELIVERED      _IO(VCHIQ_IOC_MAGIC,   17)
+#define VCHIQ_IOC_MAX                  17
 
 #endif
Index: src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_util.c
diff -u src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_util.c:1.2 src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_util.c:1.3
--- src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_util.c:1.2	Thu Mar 27 23:03:07 2014
+++ src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_util.c	Thu Jan 12 05:41:25 2017
@@ -45,6 +45,7 @@ int vchiu_queue_init(VCHIU_QUEUE_T *queu
 	queue->size = size;
 	queue->read = 0;
 	queue->write = 0;
+	queue->initialized = 1;
 
 	_sema_init(&queue->pop, 0);
 	_sema_init(&queue->push, 0);
@@ -75,6 +76,9 @@ int vchiu_queue_is_full(VCHIU_QUEUE_T *q
 
 void vchiu_queue_push(VCHIU_QUEUE_T *queue, VCHIQ_HEADER_T *header)
 {
+	if (!queue->initialized)
+		return;
+
 	while (queue->write == queue->read + queue->size) {
 		if (down_interruptible(&queue->pop) != 0) {
 			flush_signals(current);
Index: src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_util.h
diff -u src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_util.h:1.2 src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_util.h:1.3
--- src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_util.h:1.2	Thu Sep 19 14:43:39 2013
+++ src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_util.h	Thu Jan 12 05:41:25 2017
@@ -44,6 +44,7 @@ typedef struct {
 	int size;
 	int read;
 	int write;
+	int initialized;
 
 	struct semaphore pop;
 	struct semaphore push;
@@ -63,4 +64,3 @@ extern VCHIQ_HEADER_T *vchiu_queue_peek(
 extern VCHIQ_HEADER_T *vchiu_queue_pop(VCHIU_QUEUE_T *queue);
 
 #endif
-

Index: src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_shim.c
diff -u src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_shim.c:1.5 src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_shim.c:1.6
--- src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_shim.c:1.5	Tue Sep  2 21:38:28 2014
+++ src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_shim.c	Thu Jan 12 05:41:25 2017
@@ -403,6 +403,7 @@ int32_t vchi_held_msg_release(VCHI_HELD_
 
 	return 0;
 }
+EXPORT_SYMBOL(vchi_held_msg_release);
 
 /***********************************************************
  * Name: vchi_msg_hold
@@ -448,13 +449,12 @@ int32_t vchi_msg_hold(VCHI_SERVICE_HANDL
 
 	return 0;
 }
+EXPORT_SYMBOL(vchi_msg_hold);
 
 /***********************************************************
  * Name: vchi_initialise
  *
  * Arguments: VCHI_INSTANCE_T *instance_handle
- *            VCHI_CONNECTION_T **connections
- *            const uint32_t num_connections
  *
  * Description: Initialises the hardware but does not transmit anything
  *              When run as a Host App this will be called twice hence the need
@@ -725,6 +725,36 @@ int32_t vchi_service_destroy(const VCHI_
 }
 EXPORT_SYMBOL(vchi_service_destroy);
 
+int32_t vchi_service_set_option(const VCHI_SERVICE_HANDLE_T handle,
+				VCHI_SERVICE_OPTION_T option,
+				int value)
+{
+	int32_t ret = -1;
+	SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
+	VCHIQ_SERVICE_OPTION_T vchiq_option;
+	switch (option) {
+	case VCHI_SERVICE_OPTION_TRACE:
+		vchiq_option = VCHIQ_SERVICE_OPTION_TRACE;
+		break;
+	case VCHI_SERVICE_OPTION_SYNCHRONOUS:
+		vchiq_option = VCHIQ_SERVICE_OPTION_SYNCHRONOUS;
+		break;
+	default:
+		service = NULL;
+		break;
+	}
+	if (service) {
+		VCHIQ_STATUS_T status =
+			vchiq_set_service_option(service->handle,
+						vchiq_option,
+						value);
+
+		ret = vchiq_status_to_vchi(status);
+	}
+	return ret;
+}
+EXPORT_SYMBOL(vchi_service_set_option);
+
 int32_t vchi_get_peer_version( const VCHI_SERVICE_HANDLE_T handle, short *peer_version )
 {
    int32_t ret = -1;

Added files:

Index: src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_debugfs.h
diff -u /dev/null src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_debugfs.h:1.1
--- /dev/null	Thu Jan 12 05:41:26 2017
+++ src/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_debugfs.h	Thu Jan 12 05:41:25 2017
@@ -0,0 +1,52 @@
+/**
+ * Copyright (c) 2014 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:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. 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.
+ * 3. The names of the above-listed copyright holders may not be used
+ *    to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2, as published by the Free
+ * Software Foundation.
+ *
+ * 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 OWNER 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 VCHIQ_DEBUGFS_H
+#define VCHIQ_DEBUGFS_H
+
+#include "vchiq_core.h"
+
+typedef struct vchiq_debugfs_node_struct
+{
+    struct dentry *dentry;
+} VCHIQ_DEBUGFS_NODE_T;
+
+int vchiq_debugfs_init(void);
+
+void vchiq_debugfs_deinit(void);
+
+int vchiq_debugfs_add_instance(VCHIQ_INSTANCE_T instance);
+
+void vchiq_debugfs_remove_instance(VCHIQ_INSTANCE_T instance);
+
+#endif /* VCHIQ_DEBUGFS_H */

Reply via email to